From 8fb501e96c2bd470ebf316d92fca80ffb38ce244 Mon Sep 17 00:00:00 2001 From: Eloy Lafuente Date: Tue, 3 Nov 2009 23:34:43 +0000 Subject: [PATCH] MDL-20734 empties and zeros - implemented the normalise_value() function in mysql and postgres to perform central normalisation of values for insert/ update/set_field. Now all DB drivers cast empty strings to 0 when working with numeric columns (integer and decimal) --- lib/dml/mysqli_native_moodle_database.php | 63 +++++++++++------ lib/dml/pgsql_native_moodle_database.php | 86 +++++++++++------------ 2 files changed, 82 insertions(+), 67 deletions(-) diff --git a/lib/dml/mysqli_native_moodle_database.php b/lib/dml/mysqli_native_moodle_database.php index 280ba2ae1d..05ff054829 100644 --- a/lib/dml/mysqli_native_moodle_database.php +++ b/lib/dml/mysqli_native_moodle_database.php @@ -455,6 +455,35 @@ class mysqli_native_moodle_database extends moodle_database { return $this->columns[$table]; } + /** + * Normalise values based in RDBMS dependencies (booleans, LOBs...) + * + * @param database_column_info $column column metadata corresponding with the value we are going to normalise + * @param mixed $value value we are going to normalise + * @return mixed the normalised value + */ + private function normalise_value($column, $value) { + if (is_bool($value)) { // Always, convert boolean to int + $value = (int)$value; + + } else if ($value === '') { + if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') { + $value = 0; // prevent '' problems in numeric fields + } + } + // workaround for problem with wrong enums in mysql - TODO: Out in Moodle 2.1 + if (!empty($column->enums)) { + if (is_null($value) and !$column->not_null) { + // ok - nulls allowed + } else { + if (!in_array((string)$value, $column->enums)) { + throw new dml_write_exception('Enum value '.s($value).' not allowed in field '.$field.' table '.$table.'.'); + } + } + } + return $value; + } + /** * Is db in unicode mode? * @return bool @@ -746,20 +775,7 @@ class mysqli_native_moodle_database extends moodle_database { continue; } $column = $columns[$field]; - if (is_bool($value)) { - $value = (int)$value; // prevent "false" problems - } - if (!empty($column->enums)) { - // workaround for problem with wrong enums in mysql - if (is_null($value) and !$column->not_null) { - // ok - nulls allowed - } else { - if (!in_array((string)$value, $column->enums)) { - throw new dml_write_exception('Enum value '.s($value).' not allowed in field '.$field.' table '.$table.'.'); - } - } - } - $cleaned[$field] = $value; + $cleaned[$field] = $this->normalise_value($column, $value); } return $this->insert_record_raw($table, $cleaned, $returnid, $bulk); @@ -857,10 +873,8 @@ class mysqli_native_moodle_database extends moodle_database { if (!isset($columns[$field])) { continue; } - if (is_bool($value)) { - $value = (int)$value; // prevent "false" problems - } - $cleaned[$field] = $value; + $column = $columns[$field]; + $cleaned[$field] = $this->normalise_value($column, $value); } return $this->update_record_raw($table, $cleaned, $bulk); @@ -886,14 +900,17 @@ class mysqli_native_moodle_database extends moodle_database { } list($select, $params, $type) = $this->fix_sql_params($select, $params); - if (is_bool($newvalue)) { - $newvalue = (int)$newvalue; // prevent "false" problems - } - if (is_null($newvalue)) { + // Get column metadata + $columns = $this->get_columns($table); + $column = $columns[$newfield]; + + $normalised_value = $this->normalise_value($column, $newvalue); + + if (is_null($normalised_value)) { $newfield = "$newfield = NULL"; } else { $newfield = "$newfield = ?"; - array_unshift($params, $newvalue); + array_unshift($params, $normalised_value); } $sql = "UPDATE {$this->prefix}$table SET $newfield $select"; $rawsql = $this->emulate_bound_params($sql, $params); diff --git a/lib/dml/pgsql_native_moodle_database.php b/lib/dml/pgsql_native_moodle_database.php index efdfff3776..d2be127c98 100644 --- a/lib/dml/pgsql_native_moodle_database.php +++ b/lib/dml/pgsql_native_moodle_database.php @@ -501,6 +501,30 @@ class pgsql_native_moodle_database extends moodle_database { return $this->columns[$table]; } + /** + * Normalise values based in RDBMS dependencies (booleans, LOBs...) + * + * @param database_column_info $column column metadata corresponding with the value we are going to normalise + * @param mixed $value value we are going to normalise + * @return mixed the normalised value + */ + private function normalise_value($column, $value) { + if (is_bool($value)) { // Always, convert boolean to int + $value = (int)$value; + + } else if ($column->meta_type == 'B') { // BLOB detected, we return 'blob' array instead of raw value to allow + if (!is_null($value)) { // binding/executing code later to know about its nature + $value = array('blob' => $value); + } + + } else if ($value === '') { + if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') { + $value = 0; // prevent '' problems in numeric fields + } + } + return $value; + } + /** * Is db in unicode mode? * @return bool @@ -777,25 +801,13 @@ class pgsql_native_moodle_database extends moodle_database { continue; } $column = $columns[$field]; - if ($column->meta_type == 'B') { - if (is_null($value)) { - $cleaned[$field] = null; - } else { - $blobs[$field] = $value; - $cleaned[$field] = '@#BLOB#@'; - } - continue; - - } else if (is_bool($value)) { - $value = (int)$value; // prevent false '' problems - - } else if ($value === '') { - if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') { - $value = 0; // prevent '' problems in numeric fields - } + $normalised_value = $this->normalise_value($column, $value); + if (is_array($normalised_value) && array_key_exists('blob', $normalised_value)) { + $cleaned[$field] = '@#BLOB#@'; + $blobs[$field] = $normalised_value['blob']; + } else { + $cleaned[$field] = $normalised_value; } - - $cleaned[$field] = $value; } if (empty($blobs)) { @@ -913,25 +925,13 @@ class pgsql_native_moodle_database extends moodle_database { continue; } $column = $columns[$field]; - if ($column->meta_type == 'B') { - if (is_null($value)) { - $cleaned[$field] = null; - } else { - $blobs[$field] = $value; - $cleaned[$field] = '@#BLOB#@'; - } - continue; - - } else if (is_bool($value)) { - $value = (int)$value; // prevent false '' problems - - } else if ($value === '') { - if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') { - $value = 0; // prevent '' problems in numeric fields - } + $normalised_value = $this->normalise_value($column, $value); + if (is_array($normalised_value) && array_key_exists('blob', $normalised_value)) { + $cleaned[$field] = '@#BLOB#@'; + $blobs[$field] = $normalised_value['blob']; + } else { + $cleaned[$field] = $normalised_value; } - - $cleaned[$field] = $value; } $this->update_record_raw($table, $cleaned, $bulk); @@ -981,10 +981,11 @@ class pgsql_native_moodle_database extends moodle_database { $columns = $this->get_columns($table); $column = $columns[$newfield]; - if ($column->meta_type == 'B' && $newvalue !== null) { /// If the column is a BLOB and the value is not null + $normalised_value = $this->normalise_value($column, $newvalue); + if (is_array($normalised_value) && array_key_exists('blob', $normalised_value)) { /// Update BYTEA and return - $newvalue = pg_escape_bytea($this->pgsql, $newvalue); - $sql = "UPDATE {$this->prefix}$table SET $newfield = '$newvalue'::bytea $select"; + $normalised_value = pg_escape_bytea($this->pgsql, $normalised_value['blob']); + $sql = "UPDATE {$this->prefix}$table SET $newfield = '$normalised_value'::bytea $select"; $this->query_start($sql, NULL, SQL_QUERY_UPDATE); $result = pg_query_params($this->pgsql, $sql, $params); $this->query_end($result); @@ -992,14 +993,11 @@ class pgsql_native_moodle_database extends moodle_database { return true; } - if (is_bool($newvalue)) { - $newvalue = (int)$newvalue; // prevent "false" problems - } - if (is_null($newvalue)) { + if (is_null($normalised_value)) { $newfield = "$newfield = NULL"; } else { $newfield = "$newfield = \$".$i; - $params[] = $newvalue; + $params[] = $normalised_value; } $sql = "UPDATE {$this->prefix}$table SET $newfield $select"; -- 2.39.5