From 3c17c85ae61725b200420dc376f179f992bb608f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20S=CC=8Ckoda?= Date: Tue, 2 Oct 2012 16:21:17 +0200 Subject: [PATCH] MDL-35691 fix max length calculation in pg, mysql and our bigint checker --- .../check_bigints/check_bigints.class.php | 30 ++--------------- lib/dml/mysqli_native_moodle_database.php | 32 ++++++++++++++++++- lib/dml/pgsql_native_moodle_database.php | 13 +++++++- 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/admin/tool/xmldb/actions/check_bigints/check_bigints.class.php b/admin/tool/xmldb/actions/check_bigints/check_bigints.class.php index ef7b622525d..2ec4c87c47c 100644 --- a/admin/tool/xmldb/actions/check_bigints/check_bigints.class.php +++ b/admin/tool/xmldb/actions/check_bigints/check_bigints.class.php @@ -29,9 +29,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class check_bigints extends XMLDBCheckAction { - private $correct_type; - private $dbfamily; - /** * Init method, every subclass will have its own */ @@ -51,19 +48,6 @@ class check_bigints extends XMLDBCheckAction { 'nowrongintsfound' => 'tool_xmldb', 'yeswrongintsfound' => 'tool_xmldb', )); - - // Correct fields must be type bigint for MySQL and int8 for PostgreSQL - $this->dbfamily = $DB->get_dbfamily(); - switch ($this->dbfamily) { - case 'mysql': - $this->correct_type = 'bigint'; - break; - case 'postgres': - $this->correct_type = 'int8'; - break; - default: - $this->correct_type = NULL; - } } protected function check_table(xmldb_table $xmldb_table, array $metacolumns) { @@ -87,7 +71,7 @@ class check_bigints extends XMLDBCheckAction { // Going to check this field in DB $o.='
  • ' . $this->str['field'] . ': ' . $xmldb_field->getName() . ' '; // Detect if the physical field is wrong - if ($metacolumn->type != $this->correct_type) { + if (($metacolumn->meta_type != 'I' and $metacolumn->meta_type != 'R') or $metacolumn->max_length < 10) { $o.='' . $this->str['wrong'] . ''; // Add the wrong field to the list $obj = new stdClass(); @@ -124,17 +108,7 @@ class check_bigints extends XMLDBCheckAction { foreach ($wrong_fields as $obj) { $xmldb_table = $obj->table; $xmldb_field = $obj->field; - // MySQL directly supports this - -// TODO: move this hack to generators!! - - if ($this->dbfamily == 'mysql') { - $sqlarr = $dbman->generator->getAlterFieldSQL($xmldb_table, $xmldb_field); - // PostgreSQL (XMLDB implementation) is a bit, er... imperfect. - } else if ($this->dbfamily == 'postgres') { - $sqlarr = array('ALTER TABLE ' . $DB->get_prefix() . $xmldb_table->getName() . - ' ALTER COLUMN ' . $xmldb_field->getName() . ' TYPE BIGINT;'); - } + $sqlarr = $dbman->generator->getAlterFieldSQL($xmldb_table, $xmldb_field); $r.= '
  • ' . $this->str['table'] . ': ' . $xmldb_table->getName() . '. ' . $this->str['field'] . ': ' . $xmldb_field->getName() . '
  • '; // Add to output if we have sentences diff --git a/lib/dml/mysqli_native_moodle_database.php b/lib/dml/mysqli_native_moodle_database.php index 5a91e9c91d1..de0de763397 100644 --- a/lib/dml/mysqli_native_moodle_database.php +++ b/lib/dml/mysqli_native_moodle_database.php @@ -570,7 +570,18 @@ class mysqli_native_moodle_database extends moodle_database { } else if (preg_match('/([a-z]*int[a-z]*)\((\d+)\)/i', $rawcolumn->column_type, $matches)) { $rawcolumn->data_type = $matches[1]; - $rawcolumn->character_maximum_length = $matches[2]; + // Return number of decimals, not bytes here. + if ($matches[2] >= 8) { + $rawcolumn->max_length = 18; + } else if ($matches[2] >= 4) { + $rawcolumn->max_length = 9; + } else if ($matches[2] >= 2) { + $rawcolumn->max_length = 4; + } else if ($matches[2] >= 1) { + $rawcolumn->max_length = 2; + } else { + $rawcolumn->max_length = 0; + } } else if (preg_match('/(decimal)\((\d+),(\d+)\)/i', $rawcolumn->column_type, $matches)) { $rawcolumn->data_type = $matches[1]; @@ -631,7 +642,26 @@ class mysqli_native_moodle_database extends moodle_database { $info->meta_type = 'R'; $info->unique = true; } + // Return number of decimals, not bytes here. $info->max_length = $rawcolumn->numeric_precision; + if (preg_match('/([a-z]*int[a-z]*)\((\d+)\)/i', $rawcolumn->column_type, $matches)) { + if ($matches[2] >= 8) { + $maxlength = 18; + } else if ($matches[2] >= 4) { + $maxlength = 9; + } else if ($matches[2] >= 2) { + $maxlength = 4; + } else if ($matches[2] >= 1) { + $maxlength = 2; + } else { + $maxlength = 0; + } + // It is possible that display precision is different from storage type length, + // always use the smaller value to make sure our data fits. + if ($maxlength < $info->max_length) { + $info->max_length = $maxlength; + } + } $info->unsigned = (stripos($rawcolumn->column_type, 'unsigned') !== false); $info->auto_increment= (strpos($rawcolumn->extra, 'auto_increment') !== false); diff --git a/lib/dml/pgsql_native_moodle_database.php b/lib/dml/pgsql_native_moodle_database.php index fd41e5c046f..62d754895c8 100644 --- a/lib/dml/pgsql_native_moodle_database.php +++ b/lib/dml/pgsql_native_moodle_database.php @@ -463,7 +463,18 @@ class pgsql_native_moodle_database extends moodle_database { $info->auto_increment= false; $info->has_default = ($rawcolumn->atthasdef === 't'); } - $info->max_length = $matches[1]; + // Return number of decimals, not bytes here. + if ($matches[1] >= 8) { + $info->max_length = 18; + } else if ($matches[1] >= 4) { + $info->max_length = 9; + } else if ($matches[1] >= 2) { + $info->max_length = 4; + } else if ($matches[1] >= 1) { + $info->max_length = 2; + } else { + $info->max_length = 0; + } $info->scale = null; $info->not_null = ($rawcolumn->attnotnull === 't'); if ($info->has_default) {