Merge branch 'w11_MDL-31899_m23_mysqlcolumns' of git://github.com/skodak/moodle
This commit is contained in:
@@ -544,14 +544,14 @@ class ddl_test extends UnitTestCase {
|
||||
$this->assertEqual($columns['onechar']->meta_type ,'C');
|
||||
$this->assertEqual($DB->get_field('test_table1', 'onechar', array(), IGNORE_MULTIPLE), 'Nice dflt!'); //check default has been applied
|
||||
|
||||
/// add one text field and check it
|
||||
/// add one big text field and check it
|
||||
$field = new xmldb_field('onetext');
|
||||
$field->set_attributes(XMLDB_TYPE_TEXT);
|
||||
$field->set_attributes(XMLDB_TYPE_TEXT, 'big');
|
||||
$dbman->add_field($table, $field);
|
||||
$this->assertTrue($dbman->field_exists($table, 'onetext'));
|
||||
$columns = $DB->get_columns('test_table1');
|
||||
$this->assertEqual($columns['onetext']->name ,'onetext');
|
||||
$this->assertEqual($columns['onetext']->max_length , -1);
|
||||
$this->assertEqual($columns['onetext']->max_length , -1); // -1 means unknown or big
|
||||
$this->assertEqual($columns['onetext']->scale , null);
|
||||
$this->assertEqual($columns['onetext']->not_null , false);
|
||||
$this->assertEqual($columns['onetext']->primary_key , false);
|
||||
@@ -560,6 +560,20 @@ class ddl_test extends UnitTestCase {
|
||||
$this->assertEqual($columns['onetext']->default_value, null);
|
||||
$this->assertEqual($columns['onetext']->meta_type ,'X');
|
||||
|
||||
/// add one medium text field and check it
|
||||
$field = new xmldb_field('mediumtext');
|
||||
$field->set_attributes(XMLDB_TYPE_TEXT, 'medium');
|
||||
$dbman->add_field($table, $field);
|
||||
$columns = $DB->get_columns('test_table1');
|
||||
$this->assertTrue(($columns['mediumtext']->max_length == -1) or ($columns['mediumtext']->max_length >= 16777215)); // -1 means unknown or big
|
||||
|
||||
/// add one small text field and check it
|
||||
$field = new xmldb_field('smalltext');
|
||||
$field->set_attributes(XMLDB_TYPE_TEXT, 'small');
|
||||
$dbman->add_field($table, $field);
|
||||
$columns = $DB->get_columns('test_table1');
|
||||
$this->assertTrue(($columns['smalltext']->max_length == -1) or ($columns['smalltext']->max_length >= 65535)); // -1 means unknown or big
|
||||
|
||||
/// add one binary field and check it
|
||||
$field = new xmldb_field('onebinary');
|
||||
$field->set_attributes(XMLDB_TYPE_BINARY);
|
||||
|
||||
@@ -439,7 +439,12 @@ class mysqli_native_moodle_database extends moodle_database {
|
||||
|
||||
$this->columns[$table] = array();
|
||||
|
||||
$sql = "SHOW COLUMNS FROM {$this->prefix}$table";
|
||||
$sql = "SELECT column_name, data_type, character_maximum_length, numeric_precision,
|
||||
numeric_scale, is_nullable, column_type, column_default, column_key, extra
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = '" . $this->prefix.$table . "'
|
||||
AND table_schema = '" . $this->dbname . "'
|
||||
ORDER BY ordinal_position";
|
||||
$this->query_start($sql, null, SQL_QUERY_AUX);
|
||||
$result = $this->mysqli->query($sql);
|
||||
$this->query_end(true); // Don't want to throw anything here ever. MDL-30147
|
||||
@@ -448,120 +453,196 @@ class mysqli_native_moodle_database extends moodle_database {
|
||||
return array();
|
||||
}
|
||||
|
||||
while ($rawcolumn = $result->fetch_assoc()) {
|
||||
$rawcolumn = (object)array_change_key_case($rawcolumn, CASE_LOWER);
|
||||
if ($result->num_rows > 0) {
|
||||
// standard table exists
|
||||
while ($rawcolumn = $result->fetch_assoc()) {
|
||||
$info = (object)$this->get_column_info((object)$rawcolumn);
|
||||
$this->columns[$table][$info->name] = new database_column_info($info);
|
||||
}
|
||||
$result->close();
|
||||
|
||||
$info = new stdClass();
|
||||
$info->name = $rawcolumn->field;
|
||||
$matches = null;
|
||||
} else {
|
||||
// temporary tables are not in information schema, let's try it the old way
|
||||
$result->close();
|
||||
$sql = "SHOW COLUMNS FROM {$this->prefix}$table";
|
||||
$this->query_start($sql, null, SQL_QUERY_AUX);
|
||||
$result = $this->mysqli->query($sql);
|
||||
$this->query_end(true);
|
||||
if ($result === false) {
|
||||
return array();
|
||||
}
|
||||
while ($rawcolumn = $result->fetch_assoc()) {
|
||||
$rawcolumn = (object)array_change_key_case($rawcolumn, CASE_LOWER);
|
||||
$rawcolumn->column_name = $rawcolumn->field; unset($rawcolumn->field);
|
||||
$rawcolumn->column_type = $rawcolumn->type; unset($rawcolumn->type);
|
||||
$rawcolumn->character_maximum_length = null;
|
||||
$rawcolumn->numeric_precision = null;
|
||||
$rawcolumn->numeric_scale = null;
|
||||
$rawcolumn->is_nullable = $rawcolumn->null; unset($rawcolumn->null);
|
||||
$rawcolumn->column_default = $rawcolumn->default; unset($rawcolumn->default);
|
||||
$rawcolumn->column_key = $rawcolumn->key; unset($rawcolumn->default);
|
||||
$rawcolumn->extra = ($rawcolumn->column_name === 'id') ? 'auto_increment' : '';
|
||||
|
||||
if (preg_match('/(enum|varchar)\((\d+)\)/i', $rawcolumn->type, $matches)) {
|
||||
$info->type = 'varchar';
|
||||
$info->meta_type = 'C';
|
||||
$info->max_length = $matches[2];
|
||||
$info->scale = null;
|
||||
$info->not_null = ($rawcolumn->null === 'NO');
|
||||
$info->default_value = $rawcolumn->default;
|
||||
$info->has_default = is_null($info->default_value) ? false : true;
|
||||
$info->primary_key = ($rawcolumn->key === 'PRI');
|
||||
$info->binary = false;
|
||||
$info->unsigned = null;
|
||||
$info->auto_increment= false;
|
||||
$info->unique = null;
|
||||
if (preg_match('/(enum|varchar)\((\d+)\)/i', $rawcolumn->column_type, $matches)) {
|
||||
$rawcolumn->data_type = $matches[1];
|
||||
$rawcolumn->character_maximum_length = $matches[2];
|
||||
|
||||
} 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];
|
||||
|
||||
} else if (preg_match('/(decimal)\((\d+),(\d+)\)/i', $rawcolumn->column_type, $matches)) {
|
||||
$rawcolumn->data_type = $matches[1];
|
||||
$rawcolumn->numeric_precision = $matches[2];
|
||||
$rawcolumn->numeric_scale = $matches[3];
|
||||
|
||||
} else if (preg_match('/(double|float)(\((\d+),(\d+)\))?/i', $rawcolumn->column_type, $matches)) {
|
||||
$rawcolumn->data_type = $matches[1];
|
||||
$rawcolumn->numeric_precision = isset($matches[3]) ? $matches[3] : null;
|
||||
$rawcolumn->numeric_scale = isset($matches[4]) ? $matches[4] : null;
|
||||
|
||||
} else if (preg_match('/([a-z]*text)/i', $rawcolumn->column_type, $matches)) {
|
||||
$rawcolumn->data_type = $matches[1];
|
||||
$rawcolumn->character_maximum_length = -1; // unknown
|
||||
|
||||
} else if (preg_match('/([a-z]*blob)/i', $rawcolumn->column_type, $matches)) {
|
||||
$rawcolumn->data_type = $matches[1];
|
||||
|
||||
} else if (preg_match('/([a-z]*int[a-z]*)\((\d+)\)/i', $rawcolumn->type, $matches)) {
|
||||
$info->type = $matches[1];
|
||||
$info->primary_key = ($rawcolumn->key === 'PRI');
|
||||
if ($info->primary_key) {
|
||||
$info->meta_type = 'R';
|
||||
$info->max_length = $matches[2];
|
||||
$info->scale = null;
|
||||
$info->not_null = ($rawcolumn->null === 'NO');
|
||||
$info->default_value = $rawcolumn->default;
|
||||
$info->has_default = is_null($info->default_value) ? false : true;
|
||||
$info->binary = false;
|
||||
$info->unsigned = (stripos($rawcolumn->type, 'unsigned') !== false);
|
||||
$info->auto_increment= true;
|
||||
$info->unique = true;
|
||||
} else {
|
||||
$info->meta_type = 'I';
|
||||
$info->max_length = $matches[2];
|
||||
$info->scale = null;
|
||||
$info->not_null = ($rawcolumn->null === 'NO');
|
||||
$info->default_value = $rawcolumn->default;
|
||||
$info->has_default = is_null($info->default_value) ? false : true;
|
||||
$info->binary = false;
|
||||
$info->unsigned = (stripos($rawcolumn->type, 'unsigned') !== false);
|
||||
$info->auto_increment= false;
|
||||
$info->unique = null;
|
||||
$rawcolumn->data_type = $rawcolumn->column_type;
|
||||
}
|
||||
|
||||
} else if (preg_match('/(decimal)\((\d+),(\d+)\)/i', $rawcolumn->type, $matches)) {
|
||||
$info->type = $matches[1];
|
||||
$info->meta_type = 'N';
|
||||
$info->max_length = $matches[2];
|
||||
$info->scale = $matches[3];
|
||||
$info->not_null = ($rawcolumn->null === 'NO');
|
||||
$info->default_value = $rawcolumn->default;
|
||||
$info->has_default = is_null($info->default_value) ? false : true;
|
||||
$info->primary_key = ($rawcolumn->key === 'PRI');
|
||||
$info->binary = false;
|
||||
$info->unsigned = (stripos($rawcolumn->type, 'unsigned') !== false);
|
||||
$info->auto_increment= false;
|
||||
$info->unique = null;
|
||||
|
||||
} else if (preg_match('/(double|float)(\((\d+),(\d+)\))?/i', $rawcolumn->type, $matches)) {
|
||||
$info->type = $matches[1];
|
||||
$info->meta_type = 'N';
|
||||
$info->max_length = isset($matches[3]) ? $matches[3] : null;
|
||||
$info->scale = isset($matches[4]) ? $matches[4] : null;
|
||||
$info->not_null = ($rawcolumn->null === 'NO');
|
||||
$info->default_value = $rawcolumn->default;
|
||||
$info->has_default = is_null($info->default_value) ? false : true;
|
||||
$info->primary_key = ($rawcolumn->key === 'PRI');
|
||||
$info->binary = false;
|
||||
$info->unsigned = (stripos($rawcolumn->type, 'unsigned') !== false);
|
||||
$info->auto_increment= false;
|
||||
$info->unique = null;
|
||||
|
||||
} else if (preg_match('/([a-z]*text)/i', $rawcolumn->type, $matches)) {
|
||||
$info->type = $matches[1];
|
||||
$info->meta_type = 'X';
|
||||
$info->max_length = -1;
|
||||
$info->scale = null;
|
||||
$info->not_null = ($rawcolumn->null === 'NO');
|
||||
$info->default_value = $rawcolumn->default;
|
||||
$info->has_default = is_null($info->default_value) ? false : true;
|
||||
$info->primary_key = ($rawcolumn->key === 'PRI');
|
||||
$info->binary = false;
|
||||
$info->unsigned = null;
|
||||
$info->auto_increment= false;
|
||||
$info->unique = null;
|
||||
|
||||
} else if (preg_match('/([a-z]*blob)/i', $rawcolumn->type, $matches)) {
|
||||
$info->type = $matches[1];
|
||||
$info->meta_type = 'B';
|
||||
$info->max_length = -1;
|
||||
$info->scale = null;
|
||||
$info->not_null = ($rawcolumn->null === 'NO');
|
||||
$info->default_value = $rawcolumn->default;
|
||||
$info->has_default = is_null($info->default_value) ? false : true;
|
||||
$info->primary_key = false;
|
||||
$info->binary = true;
|
||||
$info->unsigned = null;
|
||||
$info->auto_increment= false;
|
||||
$info->unique = null;
|
||||
|
||||
$info = $this->get_column_info($rawcolumn);
|
||||
$this->columns[$table][$info->name] = new database_column_info($info);
|
||||
}
|
||||
|
||||
$this->columns[$table][$info->name] = new database_column_info($info);
|
||||
$result->close();
|
||||
}
|
||||
|
||||
$result->close();
|
||||
|
||||
return $this->columns[$table];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns moodle column info for raw column from information schema.
|
||||
* @param stdClass $rawcolumn
|
||||
* @return stdClass standardised colum info
|
||||
*/
|
||||
private function get_column_info(stdClass $rawcolumn) {
|
||||
$rawcolumn = (object)$rawcolumn;
|
||||
$info = new stdClass();
|
||||
$info->name = $rawcolumn->column_name;
|
||||
$info->type = $rawcolumn->data_type;
|
||||
$info->meta_type = $this->mysqltype2moodletype($rawcolumn->data_type);
|
||||
$info->default_value = $rawcolumn->column_default;
|
||||
$info->has_default = !is_null($rawcolumn->column_default);
|
||||
$info->not_null = ($rawcolumn->is_nullable === 'NO');
|
||||
$info->primary_key = ($rawcolumn->column_key === 'PRI');
|
||||
$info->binary = false;
|
||||
$info->unsigned = null;
|
||||
$info->auto_increment = false;
|
||||
$info->unique = null;
|
||||
$info->scale = null;
|
||||
|
||||
if ($info->meta_type === 'C') {
|
||||
$info->max_length = $rawcolumn->character_maximum_length;
|
||||
|
||||
} else if ($info->meta_type === 'I') {
|
||||
if ($info->primary_key) {
|
||||
$info->meta_type = 'R';
|
||||
$info->unique = true;
|
||||
}
|
||||
$info->max_length = $rawcolumn->numeric_precision;
|
||||
$info->unsigned = (stripos($rawcolumn->column_type, 'unsigned') !== false);
|
||||
$info->auto_increment= (strpos($rawcolumn->extra, 'auto_increment') !== false);
|
||||
|
||||
} else if ($info->meta_type === 'N') {
|
||||
$info->max_length = $rawcolumn->numeric_precision;
|
||||
$info->scale = $rawcolumn->numeric_scale;
|
||||
$info->unsigned = (stripos($rawcolumn->column_type, 'unsigned') !== false);
|
||||
|
||||
} else if ($info->meta_type === 'X') {
|
||||
if ("$rawcolumn->character_maximum_length" === '4294967295') { // watch out for PHP max int limits!
|
||||
// means maximum moodle size for text column, in other drivers it may also mean unknown size
|
||||
$info->max_length = -1;
|
||||
} else {
|
||||
$info->max_length = $rawcolumn->character_maximum_length;
|
||||
}
|
||||
$info->primary_key = false;
|
||||
|
||||
} else if ($info->meta_type === 'B') {
|
||||
$info->max_length = -1;
|
||||
$info->primary_key = false;
|
||||
$info->binary = true;
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise column type.
|
||||
* @param string $mysql_type
|
||||
* @return string one character
|
||||
* @throws dml_exception
|
||||
*/
|
||||
private function mysqltype2moodletype($mysql_type) {
|
||||
$type = null;
|
||||
|
||||
switch(strtoupper($mysql_type)) {
|
||||
case 'BIT':
|
||||
$type = 'L';
|
||||
break;
|
||||
|
||||
case 'TINYINT':
|
||||
case 'SMALLINT':
|
||||
case 'MEDIUMINT':
|
||||
case 'INT':
|
||||
case 'BIGINT':
|
||||
$type = 'I';
|
||||
break;
|
||||
|
||||
case 'FLOAT':
|
||||
case 'DOUBLE':
|
||||
case 'DECIMAL':
|
||||
$type = 'N';
|
||||
break;
|
||||
|
||||
case 'CHAR':
|
||||
case 'ENUM':
|
||||
case 'SET':
|
||||
case 'VARCHAR':
|
||||
$type = 'C';
|
||||
break;
|
||||
|
||||
case 'TINYTEXT':
|
||||
case 'TEXT':
|
||||
case 'MEDIUMTEXT':
|
||||
case 'LONGTEXT':
|
||||
$type = 'X';
|
||||
break;
|
||||
|
||||
case 'BINARY':
|
||||
case 'VARBINARY':
|
||||
case 'BLOB':
|
||||
case 'TINYBLOB':
|
||||
case 'MEDIUMBLOB':
|
||||
case 'LONGBLOB':
|
||||
$type = 'B';
|
||||
break;
|
||||
|
||||
case 'DATE':
|
||||
case 'TIME':
|
||||
case 'DATETIME':
|
||||
case 'TIMESTAMP':
|
||||
case 'YEAR':
|
||||
$type = 'D';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$type) {
|
||||
throw new dml_exception('invalidmysqlnativetype', $mysql_type);
|
||||
}
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise values based in RDBMS dependencies (booleans, LOBs...)
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user