MDL-29416 oracle - xmldb report to change all BYTE semantics to CHAR
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Fri, 23 Sep 2011 00:29:58 +0000 (02:29 +0200)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Sun, 25 Sep 2011 22:54:25 +0000 (00:54 +0200)
admin/tool/xmldb/actions/check_oracle_semantics/check_oracle_semantics.class.php [new file with mode: 0644]
admin/tool/xmldb/actions/main_view/main_view.class.php
admin/tool/xmldb/lang/en/tool_xmldb.php

diff --git a/admin/tool/xmldb/actions/check_oracle_semantics/check_oracle_semantics.class.php b/admin/tool/xmldb/actions/check_oracle_semantics/check_oracle_semantics.class.php
new file mode 100644 (file)
index 0000000..97248cd
--- /dev/null
@@ -0,0 +1,153 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * @package   xmldb-editor
+ * @copyright 2011 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * This class will check all the varchar2() columns
+ * in the Moodle installed DB, looking for incorrect (INT)
+ * length semanticas providing one SQL script to fix all
+ * them by changing to cross-db (CHAR) length semantics.
+ * See MDL-29322 for more details.
+ *
+ * @package   xmldb-editor
+ * @copyright 2011 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class check_oracle_semantics extends XMLDBCheckAction {
+
+    /**
+     * Init method, every subclass will have its own
+     */
+    function init() {
+        $this->introstr = 'confirmcheckoraclesemantics';
+        parent::init();
+
+        // Set own core attributes
+
+        // Set own custom attributes
+
+        // Get needed strings
+        $this->loadStrings(array(
+            'wrongoraclesemantics' => 'tool_xmldb',
+            'nowrongoraclesemanticsfound' => 'tool_xmldb',
+            'yeswrongoraclesemanticsfound' => 'tool_xmldb',
+            'expected' => 'tool_xmldb',
+            'actual' => 'tool_xmldb',
+        ));
+    }
+
+    protected function check_table(xmldb_table $xmldb_table, array $metacolumns) {
+        global $DB;
+        $o = '';
+        $wrong_fields = array();
+
+        // Get and process XMLDB fields
+        if ($xmldb_fields = $xmldb_table->getFields()) {
+            $o .= '<ul>';
+            foreach ($xmldb_fields as $xmldb_field) {
+
+                // Get the type of the column, we only will process CHAR (VARCHAR2) ones
+                if ($xmldb_field->getType() != XMLDB_TYPE_CHAR) {
+                    continue;
+                }
+
+                $o.='<li>' . $this->str['field'] . ': ' . $xmldb_field->getName() . ' ';
+
+                // Get current semantic from dictionary, we only will process B (BYTE) ones
+                // suplying the SQL code to change them to C (CHAR) semantic
+                $params = array(
+                    'table_name' => textlib::strtoupper($DB->get_prefix() . $xmldb_table->getName()),
+                    'column_name' => textlib::strtoupper($xmldb_field->getName()),
+                    'data_type' => 'VARCHAR2');
+                $currentsemantic = $DB->get_field_sql('
+                    SELECT char_used
+                      FROM user_tab_columns
+                     WHERE table_name = :table_name
+                       AND column_name = :column_name
+                       AND data_type = :data_type', $params);
+
+                // If using byte semantics, we'll need to change them to char semantics
+                if ($currentsemantic == 'B') {
+                    $info = '(' . $this->str['expected'] . " 'CHAR', " . $this->str['actual'] . " 'BYTE')";
+                    $o .= '<font color="red">' . $this->str['wrong'] . " $info</font>";
+                    // Add the wrong field to the list
+                    $obj = new stdClass();
+                    $obj->table = $xmldb_table;
+                    $obj->field = $xmldb_field;
+                    $wrong_fields[] = $obj;
+                } else {
+                    $o .= '<font color="green">' . $this->str['ok'] . '</font>';
+                }
+                $o .= '</li>';
+            }
+            $o .= '</ul>';
+        }
+
+        return array($o, $wrong_fields);
+    }
+
+    protected function display_results(array $wrong_fields) {
+        global $DB;
+        $dbman = $DB->get_manager();
+
+        $s = '';
+        $r = '<table class="generalbox boxaligncenter boxwidthwide" border="0" cellpadding="5" cellspacing="0" id="results">';
+        $r.= '  <tr><td class="generalboxcontent">';
+        $r.= '    <h2 class="main">' . $this->str['searchresults'] . '</h2>';
+        $r.= '    <p class="centerpara">' . $this->str['wrongoraclesemantics'] . ': ' . count($wrong_fields) . '</p>';
+        $r.= '  </td></tr>';
+        $r.= '  <tr><td class="generalboxcontent">';
+
+        // If we have found wrong defaults inform about them
+        if (count($wrong_fields)) {
+            $r.= '    <p class="centerpara">' . $this->str['yeswrongoraclesemanticsfound'] . '</p>';
+            $r.= '        <ul>';
+            foreach ($wrong_fields as $obj) {
+                $xmldb_table = $obj->table;
+                $xmldb_field = $obj->field;
+
+                $r.= '            <li>' . $this->str['table'] . ': ' . $xmldb_table->getName() . '. ' .
+                                          $this->str['field'] . ': ' . $xmldb_field->getName() . ', ' .
+                                          $this->str['expected'] . ' ' . "'CHAR'" . ' ' .
+                                          $this->str['actual'] . ' ' . "'BYTE'" . '</li>';
+
+                $sql = 'ALTER TABLE ' . $DB->get_prefix() . $xmldb_table->getName() . ' MODIFY ' .
+                       $xmldb_field->getName() . ' VARCHAR2(' . $xmldb_field->getLength() . ' CHAR)';
+                $sql = $dbman->generator->getEndedStatements($sql);
+                $s.= '<code>' . str_replace("\n", '<br />', $sql) . '</code><br />';
+            }
+            $r.= '        </ul>';
+            // Add the SQL statements (all together)
+            $r.= '<hr />' . $s;
+        } else {
+            $r.= '    <p class="centerpara">' . $this->str['nowrongoraclesemanticsfound'] . '</p>';
+        }
+        $r.= '  </td></tr>';
+        $r.= '  <tr><td class="generalboxcontent">';
+        // Add the complete log message
+        $r.= '    <p class="centerpara">' . $this->str['completelogbelow'] . '</p>';
+        $r.= '  </td></tr>';
+        $r.= '</table>';
+
+        return $r;
+    }
+}
index 833cea1..73d6b9f 100644 (file)
@@ -58,6 +58,7 @@ class main_view extends XMLDBAction {
             'checkdefaults' => 'tool_xmldb',
             'checkforeignkeys' => 'tool_xmldb',
             'checkbigints' => 'tool_xmldb',
+            'checkoraclesemantics' => 'tool_xmldb',
             'doc' => 'tool_xmldb',
             'viewxml' => 'tool_xmldb',
             'pendingchangescannotbesavedreload' => 'tool_xmldb'
@@ -105,6 +106,10 @@ class main_view extends XMLDBAction {
         if ($DB->get_dbfamily() == 'mysql' || $DB->get_dbfamily() == 'postgres') {
             $b .= '&nbsp;<a href="index.php?action=check_bigints&amp;sesskey=' . sesskey() . '">[' . $this->str['checkbigints'] . ']</a>';
         }
+    /// The check semantics button (only for Oracle) MDL-29416
+        if ($DB->get_dbfamily() == 'oracle') {
+            $b .= '&nbsp;<a href="index.php?action=check_oracle_semantics&amp;sesskey=' . sesskey() . '">[' . $this->str['checkoraclesemantics'] . ']</a>';
+        }
         $b .= '&nbsp;<a href="index.php?action=check_foreign_keys&amp;sesskey=' . sesskey() . '">[' . $this->str['checkforeignkeys'] . ']</a>';
         $b .= '</p>';
     /// Send buttons to output
index d95ca7c..1c2a350 100644 (file)
@@ -50,6 +50,10 @@ $string['confirmcheckindexes'] = 'This functionality will search for potential m
 Once generated you can copy such statements and execute them safely with your favourite SQL interface (don\'t forget to backup your data before doing that).<br /><br />
 It\'s highly recommended to be running the latest (+ version) available of your Moodle release (1.8, 1.9, 2.x ...) before executing the search of missing indexes.<br /><br />
 This functionality doesn\'t perform any action against the DB (just reads from it), so can be safely executed at any moment.';
+$string['confirmcheckoraclesemantics'] = 'This functionality will search for <a href="http://tracker.moodle.org/browse/MDL-29322">Oracle varchar2 columns using BYTE semantics</a> in your Moodle server, generating (but not executing!) automatically the needed SQL statements to have all the columns converted to use CHAR semantics instead (better for cross-db compatibility and increased contents max. length).<br /><br />
+Once generated you can copy such statements and execute them safely with your favourite SQL interface (don\'t forget to backup your data before doing that).<br /><br />
+It\'s highly recommended to be running the latest (+ version) available of your Moodle release (2.2, 2.3, 2.x ...) before executing the search of BYTE semantics.<br /><br />
+This functionality doesn\'t perform any action against the DB (just reads from it), so can be safely executed at any moment.';
 $string['confirmrevertchanges'] = 'Are you absolutely sure that you want to revert changes performed over:';
 $string['create'] = 'Create';
 $string['createtable'] = 'Create table:';
@@ -103,6 +107,8 @@ $string['checkforeignkeys'] = 'Check foreign keys';
 $string['check_foreign_keys'] = 'Look for foreign key violations';
 $string['checkindexes'] = 'Check indexes';
 $string['check_indexes'] = 'Look for missing DB indexes';
+$string['checkoraclesemantics'] = 'Check semantics';
+$string['check_oracle_semantics'] = 'Look for incorrect length semantics';
 $string['incorrectfieldname'] = 'Incorrect name';
 $string['index'] = 'Index';
 $string['indexes'] = 'Indexes';
@@ -130,6 +136,7 @@ $string['nomissingindexesfound'] = 'No missing indexes have been found, your DB
 $string['noviolatedforeignkeysfound'] = 'No violated foreign keys found';
 $string['nowrongdefaultsfound'] = 'No inconsistent default values have been found, your DB does not need further actions.';
 $string['nowrongintsfound'] = 'No wrong integers have been found, your DB doesn\'t need further actions.';
+$string['nowrongoraclesemanticsfound'] = 'No Oracle columns using BYTE semantics have been found, your DB doesn\'t need further actions.';
 $string['numberincorrectdecimals'] = 'Incorrect number of decimals for number field';
 $string['numberincorrectlength'] = 'Incorrect length for number field';
 $string['pendingchanges'] = 'Note: You have performed changes to this file. They can be saved at any moment.';
@@ -172,6 +179,8 @@ $string['wrongdefaults'] = 'Wrong defaults found';
 $string['wrongints'] = 'Wrong integers found';
 $string['wronglengthforenum'] = 'Incorrect length for enum field';
 $string['wrongreservedwords'] = 'Currently used reserved words<br />(note that table names aren\'t important if using $CFG->prefix)';
+$string['wrongoraclesemantics'] = 'Wrong Oracle BYTE semantics found';
 $string['yesmissingindexesfound'] = 'Some missing indexes have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to create all them (don\'t forget to backup your data before doing that).<br /><br />After doing that, it\'s highly recommended to execute this utility again to check that no more missing indexes are found.';
 $string['yeswrongdefaultsfound'] = 'Some inconsistent defaults have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to fix them all (don\'t forget to backup your data before doing that).<br /><br />After doing that, it\'s highly recommended to execute this utility again to check that no more inconsistent defaults are found.';
 $string['yeswrongintsfound'] = 'Some wrong integers have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to create all them (don\'t forget to backup your data before doing that).<br /><br />After doing that, it\'s highly recommended to execute this utility again to check that no more wrong integers are found.';
+$string['yeswrongoraclesemanticsfound'] = 'Some Oracle columns using BYTE semantics have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to create all them (don\'t forget to backup your data before doing that).<br /><br />After doing that, it\'s highly recommended to execute this utility again to check that no more wrong semantics are found.';