_ci =& get_instance(); // get code igniter instance // Loads DB conns and confs using system settings $this->_ci->load->database('system'); // Loads dbskel configs $this->_ci->config->load('dbskel'); // Loads library EPrintfLib $this->_ci->load->library('EPrintfLib'); } //------------------------------------------------------------------------------------------------------------------ // Public methods /** * Starts the DBSkel procedure * Returns false on failure and true on success * All errors/warnings/infos are printed here using EPrintfLib * Accept the step parameter that can be used to run only a wanted step */ public function start($steps, $selectedDirectories) { $start = false; // Checks if DBSkel is enabled if ($this->_ci->config->item(self::CONF_ENABLED) === true) { // Checks if the given steps parameter is fine if ($this->_checkParameterStep($steps)) { $this->_printSchemaSeparator(); $this->_printRunningMode(); // By default perform all steps $stepsArray = range(1, self::MAX_STEPS); // If steps parameter is given then use it to select the steps to be performed if ($steps != null) $stepsArray = explode(self::SEPARATOR, $steps); // Gets all the directories in application/dbskel $directories = glob(self::DBSKEL_DIR.'*', GLOB_ONLYDIR); // Checks if the selectedDirectories parameter is fine if ($this->_checkParameterSelectedDirectories($selectedDirectories, $directories)) { $start = $this->_processDirectories($directories, $stepsArray); $this->_printSchemaSeparator(); } } } else { $this->_printInfo('DBSkel is NOT enabled'); } return $start; } //------------------------------------------------------------------------------------------------------------------ // Private methods /** * Process every single directory present in dbskel directory */ private function _processDirectories($directories, $stepsArray) { $processDirectories = false; // failure by default // For each directory foreach ($directories as $directory) { $processDirectories = false; // Reset to false at the beginning of each loop $this->_printSchemaSeparator(); $this->_printInfo('Found directory >>> '.basename($directory).' <<<'); // NOTE: the order in which these methods are called has a meaning! // If a step fails then the loop is stopped // 0 - Checks file naming convention in current directory // NOTE: no need to check a failure! NOT a blocking check!! Always performed!!! $this->_checkFilenaming($directory); $this->_printFileSeparator(); // 1 - Process schema file if (in_array(self::STEP_SCHEMA, $stepsArray)) { if (!$this->_processSchemaFile($directory)) break; $this->_printFileSeparator(); } // 2 - Process sequence file if (in_array(self::STEP_SEQUENCES, $stepsArray)) { if (!$this->_processSequencesFile($directory)) break; $this->_printFileSeparator(); } // 3 - Process table files if (in_array(self::STEP_TABLES, $stepsArray)) { if (!$this->_processTableFiles($directory)) break; $this->_printFileSeparator(); } // 4 - Process constraints if (in_array(self::STEP_CONSTRAINTS, $stepsArray)) { if (!$this->_processConstraintsFile($directory)) break; $this->_printFileSeparator(); } // 5 - Process views file if (in_array(self::STEP_VIEWS, $stepsArray)) { if (!$this->_processViewsFile($directory)) break; $this->_printFileSeparator(); } // 6 - Process functions file if (in_array(self::STEP_FUNCTIONS, $stepsArray)) { if (!$this->_processFunctionsFile($directory)) break; $this->_printFileSeparator(); } // 7 - Process grants file if (in_array(self::STEP_GRANTS, $stepsArray)) { if (!$this->_processGrantsFile($directory)) break; $this->_printFileSeparator(); } // 8 - Process extra file if (in_array(self::STEP_EXTRA, $stepsArray)) { if (!$this->_processExtraFile($directory)) break; } $processDirectories = true; // If all the steps ends successfully $this->_printSchemaSeparator(); } return $processDirectories; } /** * Checks file names are compliant with the file naming convention */ private function _checkFilenaming($directory) { $files = array_filter(glob($directory.'/*'), 'is_file'); // For each file foreach ($files as $file) { $fileName = basename($file); // File name // If the file name is NOT compliant with the file naming convention if (!$this->_isFilenameValid($fileName)) { $this->_printInfo('Not valid file name, it is going to be ignored: '.$fileName); } } } /** * Checks if the file name is compliant with the file naming convention */ private function _isFilenameValid($fileName) { return $fileName == self::SCHEMA_FILENAME // Schema file || $fileName == self::SEQUENCES_FILENAME // Sequences file || (substr($fileName, 0, strlen(self::TABLE_PREFIX)) == self::TABLE_PREFIX && substr($fileName, -4, strlen(self::PHP_EXT)) == self::PHP_EXT) // Table files || $fileName == self::CONSTRAINTS_FILENAME // Constraints file || $fileName == self::VIEWS_FILENAME // Views file || $fileName == self::FUNCTIONS_FILENAME // Function file || $fileName == self::GRANTS_FILENAME // Grants file || $fileName == self::EXTRA_FILENAME; // Extra file } /** * Process the schema file */ private function _processSchemaFile($directory) { // Looks for a schema file $files = array_filter(glob($directory.'/'.self::SCHEMA_FILENAME), 'is_file'); // If a schema file is found... if (count($files) > 0) { $this->_printMessage('Found schema file: '.$files[0]); //...process it! if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> would be executed in new and diff mode'); } else // new or diff mode { return $this->_execSQLFile($files[0]); } } else { $this->_printMessage('No schema file found'); } return true; // If no files are found then go forward -> is a success } /** * Process sequences file * - Looks for sequences present in current schema, then sequences that are NOT present in php file are dropped (diff mode only) * - Looks for sequences present in php files, then sequences that are NOT present in database are installed */ private function _processSequencesFile($directory) { // Looks for a sequences file $files = array_filter(glob($directory.'/'.self::SEQUENCES_FILENAME), 'is_file'); // If a sequences file is found... if (count($files) > 0) { $this->_printMessage('Found sequences file: '.$files[0]); //...process it! require_once($files[0]); // Read sequences file $schema = basename($directory); // retrieves schema name from directory path $dbSequencesArray = $this->_listSequencesBySchema($schema); // get list of sequences currently present in DB schema // Loops through list of sequences currently present in database foreach ($dbSequencesArray as $dbSequence) { // If NOT in new mode and if the sequence present in database is NOT present in the list of sequences from php file if (!$this->_isNewMode() && !array_key_exists($dbSequence, $sequencesArray)) { if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> sequence '.$dbSequence.' NOT found in sequences file >> would be removed in diff mode'); } elseif ($this->_isDiffMode()) // only if in diff mode { // Then drop it and objects that depends on it from database! If it fails then ends execution if (!$this->_execQuery(sprintf('DROP SEQUENCE %s.%s CASCADE', $schema, $dbSequence))) { $this->_printError('Error occurred while dropping sequence: '.$dbSequence); return false; } else { $this->_printMessage('Sequence dropped successfully: '.$dbSequence); } } } } // Loops through list of sequences from php file foreach ($sequencesArray as $sequenceName => $sequenceSQL) { // If the sequence from php file is NOT present in database if (!in_array($sequenceName, $dbSequencesArray)) { if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> sequence '.$sequenceName.' NOT found database >> would be added in new and diff mode'); } else { // Then install it! If it fails then ends execution if (!$this->_execQuery($sequenceSQL)) { $this->_printError('Error occurred while adding sequence: '.$sequenceName); return false; } else { $this->_printMessage('Sequence added successfully: '.$sequenceName); } } } else { $this->_printMessage('Sequence already present in database: '.$sequenceName); } } } else { $this->_printMessage('No sequences file found'); } return true; // If ends of procedure with no failures or no files are found then is a success } /** * Process table files */ private function _processTableFiles($directory) { // Looks for table files $files = array_filter(glob($directory.'/'.self::TABLE_PREFIX.'*'.self::PHP_EXT), 'is_file'); // If table files are found... if (count($files) > 0) { //...process them! $schema = basename($directory); // retrieves schema name from directory path $dbTablesArray = $this->_listTablesBySchema($schema); // get list of tables currently present in DB schema // For each table file foreach ($files as $file) { $this->_printMessage('Found table file: '.$file); require_once($file); // Read table file // Loops through list of tables currently present in database foreach ($dbTablesArray as $dbTable) { // If NOT in new mode and if the table present in database is NOT present in the php table file if (!$this->_isNewMode() && !array_key_exists($dbTable, $tableArray)) { if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> table '.$dbTable.' NOT found in table file >> would be removed in diff mode'); } elseif ($this->_isDiffMode()) // only if in diff mode { // Then drop it! If it fails then ends execution if (!$this->_execQuery(sprintf('DROP TABLE %s.%s', $schema, $dbTable))) { $this->_printError('Error occurred while dropping table: '.$dbTable); return false; } else { $this->_printMessage('Table dropped successfully: '.$dbTable); } } } } // Retrieves all the elements from the $tableArray except the element 'comment' $tableElements = array_keys(array_diff_key($tableArray, array(self::T_COMMENT => null))); if (is_array($tableElements) && count($tableElements) == 1) // If there is only one element left... { $tableName = $tableElements[0]; // ...then it is the name of the table // If the table from php file is NOT present in database if (!in_array($tableName, $dbTablesArray)) { if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> table '.$tableName.' would be created in new and diff mode'); } else // new and diff mode { // Then create the new table! If it fails then ends execution if ($this->_createTable($schema, $tableArray)) { $this->_printMessage('Table created successfully: '.$tableName); } else { $this->_printError('Error occurred while creating a new table: '.$tableName); return false; } } } else // if table is already present in database { $this->_printMessage('Table already present in database: '.$tableName); // Manage the differences between the table present in database and the one present in php file return $this->_manageTableColumns($schema, $tableArray); } } else // otherwise the array present in the php table file is not well formatted { $this->_printError('Table file with a bad format is going to be ignored: '.$file); } } } else { $this->_printMessage('No table files found'); } return true; // If no files are found then go forward -> is a success } /** * Process constraints file * - Looks for constraints present in current schema, then constraints that are NOT present in php file are dropped (diff mode only) * - Looks for constraints present in php files, then constraints that are NOT present in database are installed */ private function _processConstraintsFile($directory) { // Looks for a constraints file $files = array_filter(glob($directory.'/'.self::CONSTRAINTS_FILENAME), 'is_file'); // If a constraints file is found... if (count($files) > 0) { $this->_printMessage('Found constraints file: '.$files[0]); //...process it! require_once($files[0]); // Read constraints file $schema = basename($directory); // retrieves schema name from directory path $dbConstraintsArray = $this->_listConstraintsBySchema($schema); // get list of constraints currently present in DB schema $dbConstraintsNamesArray = array(); // Contains only the names of the constraints // Loops through list of constraints currently present in database foreach ($dbConstraintsArray as $dbConstraint) { $dbConstraintsNamesArray[] = $dbConstraint['name']; // Copy only the name of the constraint // If NOT in new mode and if the constraint present in database is NOT present in the list of constraints from php file if (!$this->_isNewMode() && !array_key_exists($dbConstraint['name'], $constraintsArray)) { if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> constraint '.$dbConstraint['name'].' NOT found in constraints file >> would be removed in diff mode'); } elseif ($this->_isDiffMode()) // only if in diff mode { // Then drop it and objects that depends on it from database! If it fails then ends execution if (!$this->_execQuery(sprintf('ALTER TABLE %s.%s DROP CONSTRAINT %s', $schema, $dbConstraint['table'], $dbConstraint['name']))) { $this->_printError('Error occurred while dropping constraint: '.$dbConstraint['name']); return false; } else { $this->_printMessage('Constraint dropped successfully: '.$dbConstraint['name']); } } } } // Loops through list of constraints from php file foreach ($constraintsArray as $constraintName => $constraintSQL) { // If the constraint from php file is NOT present in database if (!in_array($constraintName, $dbConstraintsNamesArray)) { if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> constraint '.$constraintName.' would be added in new and diff mode'); } else { // Then install it! If it fails then ends execution if (!$this->_execQuery($constraintSQL)) { $this->_printError('Error occurred while adding constraint: '.$constraintName); return false; } else { $this->_printMessage('Constraint added successfully: '.$constraintName); } } } else { $this->_printMessage('Constraint already present in database: '.$constraintName); } } } else { $this->_printMessage('No constraints file found'); } return true; // If ends of procedure with no failures or no files are found then is a success } /** * Process views file * - Looks for views present in current schema, then views that are NOT present in php file are dropped (diff mode only) * - Looks for views present in php files and install them all */ private function _processViewsFile($directory) { // Looks for a views file $files = array_filter(glob($directory.'/'.self::VIEWS_FILENAME), 'is_file'); // If a views file is found... if (count($files) > 0) { $this->_printMessage('Found views file: '.$files[0]); //...process it! require_once($files[0]); // Read views file $schema = basename($directory); // retrieves schema name from directory path $dbViewsArray = $this->_listViewsBySchema($schema); // get list of views currently present in DB schema // Loops through list of views currently present in database foreach ($dbViewsArray as $dbView) { // If NOT in new mode and if the view present in database is NOT present in the list of views from php file if (!$this->_isNewMode() && !array_key_exists($dbView, $viewsArray)) { if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> view '.$dbView.' NOT found in views file >> would be removed in diff mode'); } elseif ($this->_isDiffMode()) // only if in diff mode { // Then drop it and objects that depends on it from database! If it fails then ends execution if (!$this->_execQuery(sprintf('DROP VIEW %s.%s CASCADE', $schema, $dbView))) { $this->_printError('Error occurred while dropping view: '.$dbView); return false; } else { $this->_printMessage('View dropped successfully: '.$dbView); } } } } // Loops through list of views from php file foreach ($viewsArray as $viewName => $viewSQL) { if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> view '.$viewName.' would be added in new and diff mode'); } else { // Then install it! If it fails then ends execution if (!$this->_execQuery($viewSQL)) { $this->_printError('Error occurred while adding view: '.$viewName); return false; } else { $this->_printMessage('View added successfully: '.$viewName); } } } } else { $this->_printMessage('No views file found'); } return true; // If ends of procedure with no failures or no files are found then is a success } /** * Process functions file * - Looks for functions present in current schema, then functions that are NOT present in php file are dropped (diff mode only) * - Looks for functions present in php files and install them all */ private function _processFunctionsFile($directory) { // Looks for a functions file $files = array_filter(glob($directory.'/'.self::FUNCTIONS_FILENAME), 'is_file'); // If a functions file is found... if (count($files) > 0) { $this->_printMessage('Found functions file: '.$files[0]); //...process it! require_once($files[0]); // Read functions file $schema = basename($directory); // retrieves schema name from directory path $dbFunctionsArray = $this->_listFunctionsBySchema($schema); // get list of functions currently present in DB schema // Loops through list of functions currently present in database foreach ($dbFunctionsArray as $dbFunction) { // If NOT in new mode and if the function present in database is NOT present in the list of functions from php file if (!$this->_isNewMode() && !array_key_exists($dbFunction, $functionsArray)) { if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> function '.$dbFunction.' NOT found in fucntions file >> would be removed in diff mode'); } elseif ($this->_isDiffMode()) // only if in diff mode { // Then drop it and objects that depends on it from database! If it fails then ends execution if (!$this->_execQuery(sprintf('DROP FUNCTION %s.%s CASCADE', $schema, $dbFunction))) { $this->_printError('Error occurred while dropping function: '.$dbFunction); return false; } else { $this->_printMessage('Function dropped successfully: '.$dbFunction); } } } } // Loops through list of functions from php file foreach ($functionsArray as $functionName => $functionSQL) { if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> view '.$functionName.' would be added in new and diff mode'); } else { // Then install it! If it fails then ends execution if (!$this->_execQuery($functionSQL)) { $this->_printError('Error occurred while adding function: '.$functionName); return false; } else { $this->_printMessage('Function added successfully: '.$functionName); } } } } else { $this->_printMessage('No functions file found'); } return true; // If ends of procedure with no failures or no files are found then is a success } /** * Process grants file */ private function _processGrantsFile($directory) { // Looks for a grants file $files = array_filter(glob($directory.'/'.self::GRANTS_FILENAME), 'is_file'); // If a grants file is found... if (count($files) > 0) { $this->_printMessage('Found grants file: '.$files[0]); //...process it! if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> would be executed in new and diff mode'); } else // new or diff mode { return $this->_execSQLFile($files[0]); } } else { $this->_printMessage('No grants file found'); } return true; // If no files are found then go forward -> is a success } /** * Process extra file */ private function _processExtraFile($directory) { // Looks for an extra file $files = array_filter(glob($directory.'/'.self::EXTRA_FILENAME), 'is_file'); // If an extra file is found... if (count($files) > 0) { $this->_printMessage('Found extra file: '.$files[0]); //...process it! if ($this->_isDryrunMode()) // If dry run mode enabled { $this->_printInfo('Dry run >> would be executed in new and diff mode'); } else // new or diff mode { return $this->_execSQLFile($files[0]); } } else { $this->_printMessage('No extra file found'); } return true; // If no files are found then go forward -> is a success } /** * Load SQL from a file and then execute such SQL */ private function _execSQLFile($file) { $sql = file_get_contents($file); // Read the file content if ($sql === false) // If failed { $this->_printError('Error occurred while reading file: '.$file); } else // otherwise { // Exec query if ($this->_execQuery($sql) == false) // if failed { $this->_printError('Error occurred while executing SQL from file: '.$file); } else // otherwise { $this->_printMessage('Successfully executed SQL from file: '.$file); return true; } } return false; } /** * Checks if the running mode is 'dryrun' */ private function _isDryrunMode() { return $this->_ci->config->item(self::CONF_MODE) == self::RUN_MODE_DRYRUN; } /** * Checks if the running mode is 'diff' */ private function _isDiffMode() { return $this->_ci->config->item(self::CONF_MODE) == self::RUN_MODE_DIFF; } /** * Checks if the running mode is 'new' */ private function _isNewMode() { return $this->_ci->config->item(self::CONF_MODE) == self::RUN_MODE_NEW; } /** * Checks if the parameter step is correct */ private function _checkParameterStep($steps) { if ($steps != null) // if it was given { $stepsArray = explode(self::SEPARATOR, $steps); // split the string in an array foreach ($stepsArray as $step) { if (!is_numeric($step)) // if it is not a number { $this->_ci->eprintflib->printError('The given parameter must be a number or a string in the following format: 1:3:5'); return false; } elseif ($step > self::MAX_STEPS) // if it is a number but > MAX_STEPS { $this->_ci->eprintflib->printError('The maximun value for this parameter is: '.self::MAX_STEPS); return false; } elseif ($step < 1) // if it is a number but < 1 { $this->_ci->eprintflib->printError('The minimum value for this parameter is 1'); return false; } } } return true; } /** * Checks if the parameter selectedDirectories is correct and stores the result in $directories */ private function _checkParameterSelectedDirectories($selectedDirectories, &$directories) { if ($selectedDirectories != null) { $selectedDirectoriesArray = explode(self::SEPARATOR, $selectedDirectories); $found = true; foreach ($selectedDirectoriesArray as $key => $value) { $selectedDirectoriesArray[$key] = self::DBSKEL_DIR.$value; if (!in_array(self::DBSKEL_DIR.$value, $directories)) { $found = false; break; } } if ($found) { $directories = $selectedDirectoriesArray; } else { $this->_printError('One or more of the given directories does NOT exist'); return false; } } return true; } //------------------------------------------------------------------------------------------------------------------ // Private database methods /** * Executes the given query */ private function _execQuery($query) { if (!@$this->_ci->db->simple_query($query)) { $error = $this->_ci->db->error(); if (is_array($error) && isset($error['message'])) { $this->_printError($error['message']); } return false; } return true; } /** * Retrieves all the sequences present in the given database schema */ private function _listSequencesBySchema($schema) { $sequencesArray = array(); $query = sprintf('SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = \'%s\'', $schema); if ($sequences = @$this->_ci->db->query($query)) { foreach ($sequences->result() as $sequence) { $sequencesArray[] = $sequence->sequence_name; } } return $sequencesArray; } /** * Retrieves all the tables present in the given database schema */ private function _listTablesBySchema($schema) { $tablesArray = array(); $query = sprintf('SELECT table_name FROM information_schema.tables WHERE table_type = \'BASE TABLE\' AND table_schema = \'%s\'', $schema); if ($tables = @$this->_ci->db->query($query)) { foreach ($tables->result() as $table) { $tablesArray[] = $table->table_name; } } return $tablesArray; } /** * Retrieves all the constraints present in the given database schema * Returns an array with all the constraints, each element of the array is an array with two elements: * - name: the name of the constraint * - table: the name of the table where the constraint is applied * NOTE: does not retrieve NOT NULL constraints */ private function _listConstraintsBySchema($schema) { $constraintsArray = array(); $query = sprintf('SELECT constraint_name, table_name FROM information_schema.table_constraints WHERE table_schema = \'%s\' AND constraint_name NOT LIKE \'%%_not_null\'', $schema); // avoid to retrieve NOT NULL constraints if ($constraints = @$this->_ci->db->query($query)) { foreach ($constraints->result() as $constraint) { $constraintsArray[] = array('name' => $constraint->constraint_name, 'table' => $constraint->table_name); } } return $constraintsArray; } /** * Retrieves all the views present in the given database schema */ private function _listViewsBySchema($schema) { $viewsArray = array(); $query = sprintf('SELECT table_name FROM information_schema.views WHERE table_schema = \'%s\'', $schema); if ($views = @$this->_ci->db->query($query)) { foreach ($views->result() as $view) { $viewsArray[] = $view->table_name; } } return $viewsArray; } /** * Retrieves all the functions present in the given database schema */ private function _listFunctionsBySchema($schema) { $functionsArray = array(); $query = sprintf('SELECT routine_name FROM information_schema.routines WHERE specific_schema != \'pg_catalog\' AND specific_schema != \'information_schema\' AND routine_schema = \'%s\'', $schema); if ($functions = @$this->_ci->db->query($query)) { foreach ($functions->result() as $function) { $functionsArray[] = $function->routine_name; } } return $functionsArray; } /** * Retrieves all the columns from a database table */ private function _listColumns($schema, $table) { $columnsArray = array(); $query = sprintf('SELECT column_name AS name, data_type AS type, column_default AS default, is_nullable AS nullable, character_maximum_length AS string_length, numeric_precision AS number_length FROM information_schema.columns WHERE table_schema = \'%s\' AND table_name = \'%s\'', $schema, $table); if ($columns = @$this->_ci->db->query($query)) { foreach ($columns->result() as $column) { $columnsArray[] = $column->routine_name; } } return $columnsArray; } /** * Creates a new table in database using the given schema and an array that defines the table structure */ private function _createTable($schema, $tableArray) { $tableName = ''; $tableComment = ''; $tableStructure = null; // For each element of the table array from the php file foreach ($tableArray as $key => $value) { if ($key == self::T_COMMENT) // If it is the comment element { $tableComment = $value; } else // otherwise is the table structure element { $tableName = $key; $tableStructure = $value; } } // Query to create a table $query = sprintf('CREATE TABLE %s.%s (', $schema, $tableName); // Query to comment the table and its columns $queryComment = sprintf('COMMENT ON TABLE %s.%s IS \'%s\';', $schema, $tableName, $tableComment); // For each element of the table structure foreach ($tableStructure as $colName => $colStructure) { $notNull = ''; // by default the column could be null if (isset($colStructure[self::T_NULL]) && $colStructure[self::T_NULL] === false) { $notNull = 'NOT NULL'; // set to NOT NULL } $default = ''; // by default there is no default for a column if (isset($colStructure[self::T_DEFAULT])) { $default = 'DEFAULT '.$colStructure[self::T_DEFAULT]; // set as given by the table structure } // Part of the query related to this column $query .= sprintf('%s %s %s %s,', $colName, $colStructure[self::T_TYPE], $notNull, $default); // If a comment is present for this column then the query is built if (isset($colStructure[self::T_COMMENT])) { $queryComment .= sprintf('COMMENT ON COLUMN %s.%s.%s IS \'%s\';', $schema, $tableName, $colName, $colStructure[self::T_COMMENT]); } } // Removes the last comma from the query $query = substr($query, 0, strlen($query) - 1); // Close the round bracket $query .= ');'; return $this->_execQuery($query.$queryComment); // executes query and returns its result } /** * TODO * Changes the structure of a table using the given schema and an array that defines the table structure */ private function _manageTableColumns($schema, $tableArray) { $tableName = ''; $tableComment = ''; $tableStructure = null; // For each element of the table array from the php file foreach ($tableArray as $key => $value) { if ($key == self::T_COMMENT) // If it is the comment element { $tableComment = $value; } else // otherwise is the table structure element { $tableName = $key; $tableStructure = $value; } } // Comments the table $queryComment = sprintf('COMMENT ON TABLE %s.%s IS \'%s\';', $schema, $tableName, $tableComment); if ($this->_isDryrunMode()) { $this->_printInfo('Dry run >> table .'$tableName'. would be commented with: '.$queryComment); } else // new and diff mode { if (!$this->_execQuery($queryComment)) { $this->_printError('Error occurred while commenting table: '.$tableName); return false; } else { $this->_printMessage('Table successfully commented: '.$tableName); } } // Retrieves the list of columns and their attributes from database $dbTableColumns = $this->_listColumns($schema, $tableName); // For each element of the table structure foreach ($tableStructure as $colName => $colStructure) { $notNull = ''; // by default the column could be null if (isset($colStructure[self::T_NULL]) && $colStructure[self::T_NULL] === false) { $notNull = 'NOT NULL'; // set to NOT NULL } $default = ''; // by default there is no default for a column if (isset($colStructure[self::T_DEFAULT])) { $default = 'DEFAULT '.$colStructure[self::T_DEFAULT]; // set as given by the table structure } // Part of the query related to this column $query = sprintf('%s %s %s %s,', $colName, $colStructure[self::T_TYPE], $notNull, $default); // Comments a column if (isset($colStructure[self::T_COMMENT])) { if ($this->_isDryrunMode()) { $this->_printInfo('Dry run >> column '$tableName.'.'.$colName.' would be commented with: '.$colStructure[self::T_COMMENT]); } else // new and diff mode { $queryComment = sprintf('COMMENT ON COLUMN %s.%s.%s IS \'%s\';', $schema, $tableName, $colName, $colStructure[self::T_COMMENT]); if (!$this->_execQuery($queryComment)) { $this->_printError('Error occurred while commenting column: '.$tableName.'.'.$colName); return false; } else { $this->_printMessage('Column successfully commented: '.$tableName.'.'.$colName); } } } } return true; } //------------------------------------------------------------------------------------------------------------------ // Private output methods /** * */ private function _printInfo($string) { $this->_ci->eprintflib->printInfo($string); } /** * */ private function _printError($string) { $this->_ci->eprintflib->printError($string); } /** * */ private function _printMessage($string) { $this->_ci->eprintflib->printMessage($string); } /** * */ private function _printSchemaSeparator() { $this->_printInfo('--------------------------------------------------------------------------------------------'); } /** * */ private function _printFileSeparator() { $this->_printMessage('--------------------------------------------------------------------------------------------'); } /** * */ private function _printRunningMode() { if ($this->_isDryrunMode()) $this->_printInfo('>> DBSkel is running in dry run mode <<'); elseif ($this->_isNewMode()) $this->_printInfo('>> DBSkel is running in new mode <<'); elseif ($this->_isDiffMode()) $this->_printInfo('>> DBSkel is running in diff mode <<'); } }