summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/common.inc89
-rw-r--r--modules/simpletest/tests/common.test80
2 files changed, 112 insertions, 57 deletions
diff --git a/includes/common.inc b/includes/common.inc
index 6cf0fc179..080caab1b 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -5773,19 +5773,18 @@ function drupal_schema_fields_sql($table, $prefix = NULL) {
* @param $table
* The name of the table; this must exist in schema API.
* @param $object
- * The object to write. This is a reference, as defaults according to
- * the schema may be filled in on the object, as well as ID on the serial
- * type(s). Both array and object types may be passed.
+ * The object to write. This is a reference, as defaults according to the
+ * schema may be filled in on the object, as well as ID on the serial type(s).
+ * Both array and object types may be passed.
* @param $primary_keys
* If this is an update, specify the primary keys' field names. It is the
- * caller's responsibility to know if a record for this object already
- * exists in the database. If there is only 1 key, you may pass a simple string.
+ * caller's responsibility to know if a record for this object already exists
+ * in the database. If there is only 1 key, you may pass a simple string.
* @return
* Failure to write a record will return FALSE. Otherwise SAVED_NEW or
- * SAVED_UPDATED is returned depending on the operation performed. The
- * $object parameter contains values for any serial fields defined by
- * the $table. For example, $object->nid will be populated after inserting
- * a new node.
+ * SAVED_UPDATED is returned depending on the operation performed. The $object
+ * parameter contains values for any serial fields defined by the $table. For
+ * example, $object->nid will be populated after inserting a new a new node.
*/
function drupal_write_record($table, &$object, $primary_keys = array()) {
// Standardize $primary_keys to an array.
@@ -5812,55 +5811,53 @@ function drupal_write_record($table, &$object, $primary_keys = array()) {
// Go through our schema, build SQL, and when inserting, fill in defaults for
// fields that are not set.
foreach ($schema['fields'] as $field => $info) {
- // Special case -- skip serial types if we are updating.
- if ($info['type'] == 'serial' && !empty($primary_keys)) {
- continue;
+ if ($info['type'] == 'serial') {
+ // Skip serial types if we are updating.
+ if (!empty($primary_keys)) {
+ continue;
+ }
+ // Track serial field so we can helpfully populate them after the query.
+ // NOTE: Each table should come with one serial field only.
+ $serial = $field;
}
- // For inserts, populate defaults from schema if not already provided.
- if (!isset($object->$field) && empty($primary_keys) && isset($info['default'])) {
+ if (!property_exists($object, $field)) {
+ // Skip fields that are not provided, unless we are inserting and a
+ // default value is provided by the schema.
+ if (!empty($primary_keys) || !isset($info['default'])) {
+ continue;
+ }
$object->$field = $info['default'];
}
- // Track serial field so we can helpfully populate them after the query.
- // NOTE: Each table should come with one serial field only.
- if ($info['type'] == 'serial') {
- $serial = $field;
+ // Build array of fields to update or insert.
+ if (empty($info['serialize'])) {
+ $fields[$field] = $object->$field;
+ }
+ elseif (!empty($object->$field)) {
+ $fields[$field] = serialize($object->$field);
+ }
+ else {
+ $fields[$field] = '';
}
- // Build arrays for the fields and values in our query.
- if (isset($object->$field)) {
- if (empty($info['serialize'])) {
- $fields[$field] = $object->$field;
+ // Type cast to proper datatype, except when the value is NULL and the
+ // column allows this.
+ //
+ // MySQL PDO silently casts e.g. FALSE and '' to 0 when inserting the value
+ // into an integer column, but PostgreSQL PDO does not. Also type cast NULL
+ // when the column does not allow this.
+ if (!is_null($object->$field) || !empty($info['not null'])) {
+ if ($info['type'] == 'int' || $info['type'] == 'serial') {
+ $fields[$field] = (int) $fields[$field];
}
- elseif (!empty($object->$field)) {
- $fields[$field] = serialize($object->$field);
+ elseif ($info['type'] == 'float') {
+ $fields[$field] = (float) $fields[$field];
}
else {
- $fields[$field] = '';
+ $fields[$field] = (string) $fields[$field];
}
}
-
- // We don't need to care about type casting if value does not exist.
- if (!isset($fields[$field])) {
- continue;
- }
-
- // Special case -- skip null value if field allows null.
- if ($fields[$field] == NULL && $info['not null'] == FALSE) {
- continue;
- }
-
- // Type cast if field does not allow null. Required by DB API.
- if ($info['type'] == 'int' || $info['type'] == 'serial') {
- $fields[$field] = (int) $fields[$field];
- }
- elseif ($info['type'] == 'float') {
- $fields[$field] = (float) $fields[$field];
- }
- else {
- $fields[$field] = (string) $fields[$field];
- }
}
if (empty($fields)) {
diff --git a/modules/simpletest/tests/common.test b/modules/simpletest/tests/common.test
index e1a45dad2..156bb8fd8 100644
--- a/modules/simpletest/tests/common.test
+++ b/modules/simpletest/tests/common.test
@@ -1460,29 +1460,87 @@ class DrupalDataApiTest extends DrupalWebTestCase {
}
function setUp() {
- parent::setUp('taxonomy');
+ parent::setUp('database_test');
}
/**
* Test the drupal_write_record() API function.
*/
function testDrupalWriteRecord() {
- // Insert an object record for a table with a single-field primary key.
- $vocabulary = new stdClass();
- $vocabulary->name = 'test';
- $insert_result = drupal_write_record('taxonomy_vocabulary', $vocabulary);
+ // Insert a record - no columns allow NULL values.
+ $person = new stdClass();
+ $person->name = 'John';
+ $person->unknown_column = 123;
+ $insert_result = drupal_write_record('test', $person);
$this->assertTrue($insert_result == SAVED_NEW, t('Correct value returned when a record is inserted with drupal_write_record() for a table with a single-field primary key.'));
- $this->assertTrue(isset($vocabulary->vid), t('Primary key is set on record created with drupal_write_record().'));
-
- // Update the initial record after changing a property.
- $vocabulary->name = 'testing';
- $update_result = drupal_write_record('taxonomy_vocabulary', $vocabulary, array('vid'));
+ $this->assertTrue(isset($person->id), t('Primary key is set on record created with drupal_write_record().'));
+ $this->assertIdentical($person->age, 0, t('Age field set to default value.'));
+ $this->assertIdentical($person->job, 'Undefined', t('Job field set to default value.'));
+
+ // Verify that the record was inserted.
+ $result = db_query("SELECT * FROM {test} WHERE id = :id", array(':id' => $person->id))->fetchObject();
+ $this->assertIdentical($result->name, 'John', t('Name field set.'));
+ $this->assertIdentical($result->age, '0', t('Age field set to default value.'));
+ $this->assertIdentical($result->job, 'Undefined', t('Job field set to default value.'));
+ $this->assertFalse(isset($result->unknown_column), t('Unknown column was ignored.'));
+
+ // Update the newly created record.
+ $person->name = 'Peter';
+ $person->age = 27;
+ $person->job = NULL;
+ $update_result = drupal_write_record('test', $person, array('id'));
$this->assertTrue($update_result == SAVED_UPDATED, t('Correct value returned when a record updated with drupal_write_record() for table with single-field primary key.'));
+ // Verify that the record was updated.
+ $result = db_query("SELECT * FROM {test} WHERE id = :id", array(':id' => $person->id))->fetchObject();
+ $this->assertIdentical($result->name, 'Peter', t('Name field set.'));
+ $this->assertIdentical($result->age, '27', t('Age field set.'));
+ $this->assertIdentical($result->job, '', t('Job field set and cast to string.'));
+
+ // Try to insert NULL in columns that does not allow this.
+ $person = new stdClass();
+ $person->name = 'Ringo';
+ $person->age = NULL;
+ $person->job = NULL;
+ $insert_result = drupal_write_record('test', $person);
+ $this->assertTrue(isset($person->id), t('Primary key is set on record created with drupal_write_record().'));
+ $result = db_query("SELECT * FROM {test} WHERE id = :id", array(':id' => $person->id))->fetchObject();
+ $this->assertIdentical($result->name, 'Ringo', t('Name field set.'));
+ $this->assertIdentical($result->age, '0', t('Age field set.'));
+ $this->assertIdentical($result->job, '', t('Job field set.'));
+
+ // Insert a record - the "age" column allows NULL.
+ $person = new stdClass();
+ $person->name = 'Paul';
+ $person->age = NULL;
+ $insert_result = drupal_write_record('test_null', $person);
+ $this->assertTrue(isset($person->id), t('Primary key is set on record created with drupal_write_record().'));
+ $result = db_query("SELECT * FROM {test_null} WHERE id = :id", array(':id' => $person->id))->fetchObject();
+ $this->assertIdentical($result->name, 'Paul', t('Name field set.'));
+ $this->assertIdentical($result->age, NULL, t('Age field set.'));
+
+ // Insert a record - do not specify the value of a column that allows NULL.
+ $person = new stdClass();
+ $person->name = 'Meredith';
+ $insert_result = drupal_write_record('test_null', $person);
+ $this->assertTrue(isset($person->id), t('Primary key is set on record created with drupal_write_record().'));
+ $this->assertIdentical($person->age, 0, t('Age field set to default value.'));
+ $result = db_query("SELECT * FROM {test_null} WHERE id = :id", array(':id' => $person->id))->fetchObject();
+ $this->assertIdentical($result->name, 'Meredith', t('Name field set.'));
+ $this->assertIdentical($result->age, '0', t('Age field set to default value.'));
+
+ // Update the newly created record.
+ $person->name = 'Mary';
+ $person->age = NULL;
+ $update_result = drupal_write_record('test_null', $person, array('id'));
+ $result = db_query("SELECT * FROM {test_null} WHERE id = :id", array(':id' => $person->id))->fetchObject();
+ $this->assertIdentical($result->name, 'Mary', t('Name field set.'));
+ $this->assertIdentical($result->age, NULL, t('Age field set.'));
+
// Run an update query where no field values are changed. The database
// layer should return zero for number of affected rows, but
// db_write_record() should still return SAVED_UPDATED.
- $update_result = drupal_write_record('taxonomy_vocabulary', $vocabulary, array('vid'));
+ $update_result = drupal_write_record('test_null', $person, array('id'));
$this->assertTrue($update_result == SAVED_UPDATED, t('Correct value returned when a valid update is run without changing any values.'));
// Insert an object record for a table with a multi-field primary key.