diff --git a/lib/dml/mssql_native_moodle_database.php b/lib/dml/mssql_native_moodle_database.php index f32239e6c22..5029beb4f40 100644 --- a/lib/dml/mssql_native_moodle_database.php +++ b/lib/dml/mssql_native_moodle_database.php @@ -810,7 +810,7 @@ class mssql_native_moodle_database extends moodle_database { } else { unset($params['id']); if ($returnid) { - $returning = "; SELECT SCOPE_IDENTITY()"; + $returning = "OUTPUT inserted.id"; } } @@ -822,18 +822,29 @@ class mssql_native_moodle_database extends moodle_database { $qms = array_fill(0, count($params), '?'); $qms = implode(',', $qms); - $sql = "INSERT INTO {" . $table . "} ($fields) VALUES($qms) $returning"; + $sql = "INSERT INTO {" . $table . "} ($fields) $returning VALUES ($qms)"; list($sql, $params, $type) = $this->fix_sql_params($sql, $params); $rawsql = $this->emulate_bound_params($sql, $params); $this->query_start($sql, $params, SQL_QUERY_INSERT); $result = mssql_query($rawsql, $this->mssql); - $this->query_end($result); + // Expected results are: + // - true: insert ok and there isn't returned information. + // - false: insert failed and there isn't returned information. + // - resource: insert executed, need to look for returned (output) + // values to know if the insert was ok or no. Posible values + // are false = failed, integer = insert ok, id returned. + $end = false; + if (is_bool($result)) { + $end = $result; + } else if (is_resource($result)) { + $end = mssql_result($result, 0, 0); // Fetch 1st column from 1st row. + } + $this->query_end($end); // End the query with the calculated $end. if ($returning !== "") { - $row = mssql_fetch_assoc($result); - $params['id'] = reset($row); + $params['id'] = $end; } $this->free_result($result); diff --git a/lib/dml/simpletest/testdml.php b/lib/dml/simpletest/testdml.php index f7c2152b603..97954be6609 100644 --- a/lib/dml/simpletest/testdml.php +++ b/lib/dml/simpletest/testdml.php @@ -2094,6 +2094,34 @@ class dml_test extends UnitTestCase { $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id))); $id = $DB->insert_record($tablename, array('onetext' => 1e300)); $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id))); + + // Test that inserting data violating one unique key leads to error. + // Empty the table completely. + $this->assertTrue($DB->delete_records($tablename)); + + // Add one unique constraint (index). + $key = new xmldb_key('testuk', XMLDB_KEY_UNIQUE, array('course', 'oneint')); + $dbman->add_key($table, $key); + + // Let's insert one record violating the constraint multiple times. + $record = (object)array('course' => 1, 'oneint' => 1); + $this->assertTrue($DB->insert_record($tablename, $record, false)); // insert 1st. No problem expected. + + // Re-insert same record, not returning id. dml_exception expected. + try { + $DB->insert_record($tablename, $record, false); + $this->fail("Expecting an exception, none occurred"); + } catch (exception $e) { + $this->assertTrue($e instanceof dml_exception); + } + + // Re-insert same record, returning id. dml_exception expected. + try { + $DB->insert_record($tablename, $record, true); + $this->fail("Expecting an exception, none occurred"); + } catch (exception $e) { + $this->assertTrue($e instanceof dml_exception); + } } public function test_import_record() {