/[drupal]/contributions/modules/dbscripts/dbscripts.module
ViewVC logotype

Diff of /contributions/modules/dbscripts/dbscripts.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.5.4.77, Sat May 30 17:06:37 2009 UTC revision 1.5.4.78, Sat May 30 18:26:06 2009 UTC
# Line 1  Line 1 
1  <?php  <?php
2    
3  /**  /**
  * Get the database connection settings from settings.php file  
  *  
  * Helper function for dump, erase and restore functions  
  */  
 function _dbscripts_db_connect() {  
   require('config.inc');  
   require("$settings_path/settings.php");  
   
   // Ensure required files are loaded  
   if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";  
   if (!isset($db_url)) return "The file 'settings.php' file does not exist.";  
   
   preg_match('/'.$dbtype.':\/\/([^:]+):([^@]+)@([^\/]+)\/(.+)/', $db_url, $db_settings);  
   
   if (empty($db_settings)) {  
     return FALSE;  
   } else {  
   
     $dbuser = $db_settings[1];  
     $dbpassword = $db_settings[2];  
     $dbhost = $db_settings[3];  
     $dbname = $db_settings[4];  
   
     return "-u $dbuser -p$dbpassword -h $dbhost $dbname";  
   }  
 }  
   
   
 /**  
  * Get options for dump file and filtering  
  *  
  * Helper function for restore.php and dump.php  
  *  
  * @param $argv  
  *   Pass in the $_SERVER['argv'] variable to return options set when running  
  *   the script.  
  */  
 function _dbscripts_get_options($argv) {  
   // Set default filter option  
   $options['filter'] = 'full';  
   
   // Set which branch to use  
   $use_default_branch = FALSE;  
   if(isset($argv[1])) {  
     if(in_array($argv[1],array('min','none','full'))) {  
       $use_default_branch = TRUE;  
       $options['filter'] = $argv[1];  
     }  
   } else {  
     $use_default_branch = TRUE;  
   }  
   $options['branch'] = $use_default_branch ? 'development' : $argv[1];  
   
   // Set which last-merge to use  
   $use_default_lastmerge = FALSE;  
   if(isset($argv[2])) {  
     if(in_array($argv[2],array('min','none','full'))) {  
       $use_default_lastmerge = TRUE;  
       $options['filter'] = $argv[2];  
     }  
   } else {  
     $use_default_lastmerge = TRUE;  
   }  
   $options['last-merge'] = $use_default_lastmerge ? 'last-merge' : $argv[2];  
   
   // Set filter option  
   if(isset($argv[3])) {  
     if(in_array($argv[3],array('min','none','full'))) {  
       $options['filter'] = $argv[3];  
     }  
   }  
   
   return $options;  
 }  
   
   
 /**  
4   * Dump the database   * Dump the database
5   *   *
6   * @param $branch   * @param $branch
# Line 156  function dbscripts_dump($branch = 'devel Line 79  function dbscripts_dump($branch = 'devel
79    
80    // These are all the special dump options that make the database diffable    // These are all the special dump options that make the database diffable
81    // and preserve character set    // and preserve character set
82    $dump_options = "--skip-opt --add-drop-table --add-locks --create-options --quick --lock-tables --set-charset --disable-keys --order-by-primary --skip-comments --comments=FALSE --default-character-set=utf8 --character-sets-dir=$charsets --hex-blob";    $dump_options = "--skip-opt --add-drop-table --add-locks --create-options --quick --lock-tables --disable-keys --order-by-primary --skip-comments --comments=FALSE --set-charset --default-character-set=utf8 --character-sets-dir=$charsets --hex-blob";
83    
84      // Some versions of MySQL do not set character encoding for column names
85      // which can cause unnessisary changes in the version control system
86      // Enable this in config.inc
87      $charset_filter = '';
88      if ($remove_column_charset) {
89        $charset_filter .= "| sed ";
90        $charset_filter .= "-e '/SET @saved_cs_client     = @@character_set_client;/d' ";
91        $charset_filter .= "-e '/SET character_set_client = utf8;/d' ";
92        $charset_filter .= "-e '/SET character_set_client = @saved_cs_client;/d' ";
93      }
94    
95    // Dump the structure of all tables    // Dump the structure of all tables
96    foreach ($table_list as $table) {    foreach ($table_list as $table) {
97          exec("$mysqldump $dump_options --no-data $db_connection_settings --tables $table > $temp_location/tables/$table.sql");          exec("$mysqldump $dump_options --no-data $db_connection_settings --tables $table $charset_filter > $temp_location/tables/$table.sql");
98    }    }
99    
100    // Check that a file actually has data, and stop if it doesn't    // Check that a file actually has data, and stop if it doesn't
# Line 416  function dbscripts_dump($branch = 'devel Line 350  function dbscripts_dump($branch = 'devel
350  }  }
351    
352    
353    
354  /**  /**
355   * Erase the database   * Erase the database
356   *   *
# Line 478  function dbscripts_erase($filter_option Line 413  function dbscripts_erase($filter_option
413  }  }
414    
415    
416    
417  /**  /**
418   * Restore the database   * Restore the database
419   *   *
# Line 547  function dbscripts_restore($branch = 'de Line 483  function dbscripts_restore($branch = 'de
483    
484    // Restore each database file    // Restore each database file
485    foreach ($tables_restored as $table) {    foreach ($tables_restored as $table) {
486        print $debugging ? "\nrestoring $table\n" : '';
487      if (file_exists("$dump_location/tables/$table.sql")) exec("$mysql $db_connection_settings < $dump_location/tables/$table.sql");      if (file_exists("$dump_location/tables/$table.sql")) exec("$mysql $db_connection_settings < $dump_location/tables/$table.sql");
488      if (file_exists("$dump_location/data/$table.sql")) exec("$mysql $db_connection_settings < $dump_location/data/$table.sql");      if (file_exists("$dump_location/data/$table.sql")) exec("$mysql $db_connection_settings < $dump_location/data/$table.sql");
489      if (file_exists("$dump_location/data/$table-new.sql")) exec("$mysql $db_connection_settings < $dump_location/data/$table-new.sql");      if (file_exists("$dump_location/data/$table-new.sql")) exec("$mysql $db_connection_settings < $dump_location/data/$table-new.sql");
# Line 564  function dbscripts_restore($branch = 'de Line 501  function dbscripts_restore($branch = 'de
501  }  }
502    
503    
504    
505  /**  /**
506   * Merge databases   * Merge databases
507   *   *
# Line 925  function dbscripts_merge($dev_branch = ' Line 863  function dbscripts_merge($dev_branch = '
863    
864    
865  /**  /**
866   * Process an array of tables   * Raise the increments, and its foreign keys, of the given table within the
867   *   * given branch
  * When given an array of all tables, you can either remove matches  
  * from the table list, or pick only positive matches  
868   *   *
869     * @param $table
870     *   Table to raise the increments of
871     * @param $column
872     *   Column to raise the increments of
873     * @param $start_at
874     *   Range of increments within the table to start rewriting
875     * @param $change_to
876     *   Range to change rewrite the increments to.  Must be higher than both
877     *   $start_at, and the table's current increment value.  If it is not, then it
878     *   will be recalculated to be the highest value.
879   * @param $branch   * @param $branch
880   *    Which branch should be use for its list of tables   *   Branch to make the changes on.
  * @param $tables_compare  
  *    An array of table names that should be compared  
  * @param $remove_match  
  *    Should matches in $tables_compare be removed from the list, or kept  
881   */   */
882  function _dbscripts_process_tables($branch, $tables_compare, $remove_match = TRUE) {  function dbscripts_raise_table_increments($table, $start_at, $change_to, $branch = 'development', $filter_option = 'full') {
883    require('config.inc');    require('config.inc');
884      require('config.references.inc');
885    
886    // Ensure required files are loaded    // Ensure required files are loaded
887    if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";    if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version.";
888      if (!isset($tables_referenced)) return "The file 'config.references.inc' does not exist.  Copy from the example version.";
889    
890    // Set location    // Set locations
891    $branch_location = "$dump_path/$branch";    $branch_location = "$dump_path/$branch";
892      $temp_location = "$dump_path/tmp";
893    
894      // Ensure tmp directory exists
895      if (!file_exists($temp_location)) {
896         exec("mkdir -p $temp_location");
897      }
898    
899    // Check if the branch exists, otherwise fail    // Check if the branch exists, otherwise fail
900    if (!file_exists($branch_location)) {    if (!file_exists($branch_location)) {
901      return "The branch '$branch' does not exist";      print "\n\nThe branch '$branch' does not exist\n\n";
902        return FALSE;
903    }    }
904    
905    // Check if the table list file exists, otherwise fail    // Check if the table exists, otherwise fail
906    if (!file_exists("$branch_location/table_list.txt")) {    if (!file_exists("$branch_location/tables/$table.sql")) {
907      return "The branch '$branch' does not have a table_list.txt file";      print "\n\nThe table '$table' does not exist\n\n";
908        return FALSE;
909    }    }
910    
911    $tables = file("$branch_location/table_list.txt", FILE_IGNORE_NEW_LINES);    // Find all tables that use the increment as a foreign key
912    $tables_match = array();    $table_references = dbscripts_get_table_references($table, $branch, $filter_option);
913      if (!is_array($table_references)) {
914        print "\n\nERROR: ".$table_references."\n\n";
915        return FALSE;
916      }
917    
918    foreach ($tables as $key => $table) {    // Fail if there are any found possible references
919      // Since some tables are specified with a .*, generating other possible values    if (array_key_exists('found', $table_references)) {
920      $truncated = explode('_', $table);      print "\n\nFAILED:  Possible references found for table '$table'\n\n";
921      $truncated1 = isset($truncated[0]) ? $truncated[0].'_.*' : '';      print_r($table_references['found']);
922      $truncated2 = isset($truncated[1]) ? $truncated[0].'_'.$truncated[1].'_.*' : '';      print "\nUpdate '$script_path/config.reference.inc' with this reference\n\n";
923        return FALSE;
924      }
925    
926      $check_tables = array($table, $truncated1, $truncated2);    // Add system path patterns as references
927      foreach ($check_tables as $check) {    if (isset($system_paths[$table]['tables'])) {
928        if (in_array($check, $tables_compare)) {      foreach ($system_paths[$table]['tables'] as $system_path_table => $system_path_columns) {
929          $tables_match[$key] = $table;        foreach ($system_path_columns as $system_path_column) {
930            $table_references['references'][$system_path_table][] = $system_path_column;
931        }        }
932      }      }
933    }    }
934    
935    foreach ($tables_match as $key => $table) {    // Find the largest increment value between $change_to and the current
936      unset($tables[$key]);    // increment. Use the highest increment
937      $current_inc = dbscripts_get_table_increment($table, $branch);
938      if (is_array($current_inc) && $current_inc['num'] > $change_to) {
939        $change_to = $current_inc['num'];
940    }    }
941    
942    if ($remove_match) {    // Get an array of the range of increments to work with
943      return $tables;    if ($start_at < $current_inc['num']) {
944        $increment_range = range($start_at, ($current_inc['num'] - 1));
945    } else {    } else {
946      return $tables_match;      // There is nothing to do then.  Likely there are no new records.
947        return TRUE;
948    }    }
 }  
   
   
 /**  
  * Get a given table's current auto increment value  
  *  
  * @param $table  
  *    The table name you want to check  
  * @param $branch  
  *    The branch that will be checked, since each branch could  
  *    possibly have a different increment.  
  */  
 function dbscripts_get_table_increment($table, $branch) {  
   require('config.inc');  
   
   // Ensure required files are loaded  
   if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";  
949    
950    $branch_location = "$dump_path/$branch";    // Create a key=>value array of increment pairs
951      $increment_pairs = array();
952    // Check if the branch exists, otherwise fail    $increment_change = $change_to;
953    if (!file_exists($branch_location)) {    foreach ($increment_range as $increment) {
954      return "The branch '$branch' does not exist";      $increment_pairs[$increment] = $increment_change;
955        $increment_change++;
956    }    }
957    
958    $increment = FALSE;    // If there is a system paths reference, also add the pairs
959    if(file_exists("$branch_location/tables/$table.sql")) {    $pattern_pair_old = array();
960      if (exec("grep 'auto_increment' $branch_location/tables/$table.sql")) {    $pattern_pair_new = array();
961        $inc_string = exec("grep 'AUTO_INCREMENT=' $branch_location/tables/$table.sql");    $fuzzy_pattern_pair_old = array();
962      $fuzzy_pattern_pair_new = array();
963      if (isset($system_paths[$table])) {
964    
965        $increment['num'] = '0';      // Exact patterns
966        if ($inc_string) {      if (array_key_exists('patterns', $system_paths[$table])) {
967          $inc_string_parts = explode(' ', $inc_string);        $i = 0;
968          foreach ($inc_string_parts as $part) {        foreach ($system_paths[$table]['patterns'] as $key => $pattern) {
969            if (strpos($part, 'AUTO_INCREMENT=') !== FALSE) {          foreach ($increment_pairs as $old_increment => $new_increment) {
970              $increment['num'] = str_replace('AUTO_INCREMENT=', '', $part);            $pattern_pair_old[$i] = str_replace('*', $old_increment, $pattern);
971            }            $pattern_pair_new[$i] = str_replace('*', $new_increment, $pattern);
972              $i++;
973          }          }
974        }        }
   
       $id_string = exec("grep 'auto_increment' $branch_location/tables/$table.sql");  
       $id_string_parts = explode('`', $id_string);  
       $increment['id'] = $id_string_parts[1];  
975      }      }
   }  
976    
977    return $increment;      // Fuzzy patterns
978  }      if (array_key_exists('fuzzy', $system_paths[$table])) {
979          $i = 0;
980          foreach($system_paths[$table]['fuzzy'] as $key => $pattern) {
981    
982            $pattern_parts = explode('#', $pattern);
983            $strlen_pattern = FALSE;
984            foreach ($pattern_parts as $part) {
985              if (strstr($part, 'NUMLEN+')) {
986                $strlen_pattern = $part;
987              }
988            }
989            $strlen = isset($strlen_pattern) ? str_replace('NUMLEN+', '', $strlen_pattern) : FALSE;
990    
991  /**          $pattern = str_replace(array('"', '\\'), array('#DQ#', '#BS#'), $pattern);
992   * Get a list of all tables that are using auto increment          //$pattern = str_replace('\\', '#BS', $pattern);
  *  
  * @param $branch  
  *    The branch that has the tables to check  
  * @param $filter_option  
  *    What degree of filtering should be done on the tables returned, just  
  *    like when dumping and restoring.  
  */  
 function dbscripts_find_tables_with_increment($branch, $filter_option = "full") {  
   require('config.inc');  
993    
994    // Ensure required files are loaded          foreach ($increment_pairs as $old_increment => $new_increment) {
995    if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";            $search = array();
996              $replace_old = array();
997              $replace_new = array();
998    
999    // Set location            $idlen_old = strlen($old_increment);
1000    $branch_location = "$dump_path/$branch";            $idlen_new = strlen($new_increment);
1001    
1002    // Check if the branch exists, otherwise fail            $search[] = '*';
1003    if (!file_exists($branch_location)) {            $replace_old[] = $old_increment;
1004      return "The branch '$branch' does not exist";            $replace_new[] = $new_increment;
   }  
1005    
1006    // Set the filtering options, ignoring tables not being tracked            $search[] = "#NUMLEN#";
1007    $tables_ignored = array();            $replace_old[] = $idlen_old;
1008    switch($filter_option){            $replace_new[] = $idlen_new;
     case 'none':  
       break;  
1009    
1010      case 'min':            if ($strlen) {
1011        $tables_ignored = array_merge($tables_filtered, $tables_filtered_l1);              $search[] = "#".$strlen_pattern."#";
1012        break;              $replace_old[] = $strlen + $idlen_old;
1013                $replace_new[] = $strlen + $idlen_new;
1014              }
1015    
1016      default:            $fuzzy_pattern_pair_old[$i] = str_replace($search, $replace_old, $pattern);
1017        $tables_ignored = array_merge($tables_filtered, $tables_filtered_l1, $tables_filtered_l2);            $fuzzy_pattern_pair_new[$i] = str_replace($search, $replace_new, $pattern);
1018        break;            $i++;
1019    }          }
1020          }
1021        }
1022    
   $table_list = _dbscripts_process_tables($branch, $tables_ignored);  
   if (!is_array($table_list)) {  
     // Fail and pass through the message from _dbscripts_process_tables if it didn't pass an array  
     return $table_list;  
1023    }    }
1024    
1025    $list = array();    // Write these increment and pattern pairs to a file for awk to use
1026    foreach ($table_list as $table) {    exec("echo '#!/usr/bin/awk -f' > $temp_location/increment_pairs.awk");
1027      $increment = dbscripts_get_table_increment($table, $branch);    exec("echo '{' >> $temp_location/increment_pairs.awk");
1028      if ($increment && is_array($increment)) {    foreach ($increment_pairs as $increment => $target) {
1029        $list[] = $table;      exec("echo 'increment_pairs[$increment] = $target' >> $temp_location/increment_pairs.awk");
1030      } elseif ($increment != FALSE) {    }
1031        // If not FALSE and not an array, then fail and pass through the error message    if (array_key_exists('0', $pattern_pair_old)) {
1032          return $increment;      foreach ($pattern_pair_old as $key => $pattern) {
1033          exec("echo \"pattern_pair_old[$key] = \\\"'$pattern'\\\"\" >> $temp_location/increment_pairs.awk");
1034        }
1035        foreach ($pattern_pair_new as $key => $pattern) {
1036          exec("echo \"pattern_pair_new[$key] = \\\"'$pattern'\\\"\" >> $temp_location/increment_pairs.awk");
1037      }      }
1038    }    }
1039      if (array_key_exists('0', $fuzzy_pattern_pair_old)) {
1040    return $list;      foreach ($fuzzy_pattern_pair_old as $key => $pattern) {
1041  }        exec("echo \"fuzzy_pattern_pair_old[$key] = \\\"$pattern\\\"\" >> $temp_location/increment_pairs.awk");
1042        }
1043        foreach ($fuzzy_pattern_pair_new as $key => $pattern) {
1044          exec("echo \"fuzzy_pattern_pair_new[$key] = \\\"$pattern\\\"\" >> $temp_location/increment_pairs.awk");
1045        }
1046      }
1047      exec("echo '}' >> $temp_location/increment_pairs.awk");
1048    
1049    
1050      // Raise the auto_increment value of the table
1051      exec("sed 's/ AUTO_INCREMENT={$current_inc['num']} / AUTO_INCREMENT={$increment_change} /g' $branch_location/tables/$table.sql > $temp_location/$table.sql");
1052      exec("mv $temp_location/$table.sql $branch_location/tables/$table.sql");
1053    
1054  /**    // Raise the increment for all foreign keys of the given table
1055   * Return a table's primary key    foreach ($table_references['references'] as $table_to_modify => $columns_referenced) {
  *  
  * @param $table  
  *   Table to check  
  * @param $branch  
  *   Branch to check in  
  */  
 function dbscripts_get_table_primary_keys($table, $branch) {  
   require('config.inc');  
1056    
1057    // Ensure required files are loaded      // Check if this table exists and has any data stored
1058    if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";      if (
1059              file_exists("$branch_location/tables/$table_to_modify.sql") &&
1060              (
1061                file_exists("$branch_location/data/$table_to_modify.sql") ||
1062                file_exists("$branch_location/data/$table_to_modify-new.sql")
1063              )
1064            ) {
1065    
1066    // Set locations        // Create an array of the files we'll be working with (existing data and/or new data)
1067    $branch_location = "$dump_path/$branch";        $file_names = array();
1068          if (file_exists("$branch_location/data/$table_to_modify.sql")) {
1069            $file_names[] = $table_to_modify;
1070          }
1071          if (file_exists("$branch_location/data/$table_to_modify-new.sql")) {
1072            $file_names[] = $table_to_modify."-new";
1073          }
1074    
1075    if (file_exists("$branch_location/tables/$table.sql")) {        // Create a CSV version of the table's data
1076      $primary_key_line = exec("grep '^  PRIMARY KEY' $branch_location/tables/$table.sql | sed 's/`//g'");        foreach ($file_names as $file_name) {
1077      if ($primary_key_line) {          exec("
1078        $primary_key_line_parts = explode("(", $primary_key_line);              grep 'INSERT INTO' $branch_location/data/$file_name.sql \\
1079        $primary_key_line_parts = explode(")", $primary_key_line_parts[1]);              |sed -e 's/^INSERT INTO `$table_to_modify` VALUES (//g' -e 's/);$//g' \\
1080        $primary_keys = explode(",", $primary_key_line_parts[0]);              |sed -e 's/#/#PND#/g' -e \"s/\\\\\'/#SQ#/g\" -e 's/\"/#DQ#/g' -e \"s/\\\\\/#BS#/g\" \\
1081        return $primary_keys;              > $temp_location/$file_name.csv
1082      }          ");
1083    }        }
1084    
1085  }        // Create an array of the table's structure
1086          exec("grep '^  `' $branch_location/tables/$table_to_modify.sql > $temp_location/$table_to_modify.txt");
1087          $table_columns = file("$temp_location/$table_to_modify.txt", FILE_IGNORE_NEW_LINES);
1088          exec("rm $temp_location/$table_to_modify.txt");
1089    
1090          // Find out the column position
1091          $column_positions = array();
1092          $dependant_columns = array();
1093          foreach ($columns_referenced as $column_to_modify) {
1094            $found_position = FALSE;
1095            foreach ($table_columns as $key => $table_column) { // the key defines the column's position
1096    
1097              if (is_array($column_to_modify)) {
1098                // If the column_to_modify value is an array, it is a case that has dependencies
1099    
1100  /**              // Restructure the array to something more useful, with the columns' positions
1101   * Find all possible references for the given table              foreach ($column_to_modify as $column_name => $value) {
1102   *                if (strpos($table_column, "`$column_name`")) {
1103   * Helper script to make it easier to discover if there are possible references                  if ($value == '*') {
1104   * to a given table.                    $dependant_columns['foreign-key']['name'] = $column_name;
1105   *                    $dependant_columns['foreign-key']['position'] = $key;
1106   * DOES NOT GAURANTEE TO FIND ALL REFERENCES                  } else {
1107   * This is merely a tool to assist you in narrowing down possibilities and                    $dependant_columns['dependencies'][$column_name]['value'] = $value;
1108   * provide a first level of error checking for dbscripts_get_table_references.                    $dependant_columns['dependencies'][$column_name]['position'] = $key;
1109   * It is your responsibility to ensure all actual references are recorded in                  }
1110   * config.references.inc                  $found_position = TRUE;
1111   *                }
1112   * @param $table              }
  *    Table to find all references of  
  * @param $branch  
  *    Branch to check  
  * @param $filter_option  
  *    What degree of filtering should be done on the tables returned, just  
  *    like when dumping and restoring.  
  */  
 function dbscripts_find_possible_table_references($table, $branch, $filter_option = "full") {  
   require('config.inc');  
1113    
1114    // Ensure required files are loaded            } else {
1115    if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";              // but in most cases just have a single column value to find the position of
1116                if (strpos($table_column, "`$column_to_modify`")) {
1117                  $column_positions[] = $key;
1118                  $found_position = TRUE;
1119                }
1120              }
1121    
1122    // Set locations          }
1123    $branch_location = "$dump_path/$branch";          if (!$found_position) {
1124    $temp_location = "$dump_path/tmp";            print "ERROR: Didn't find column '$column_to_modify' in '$table_to_modify' when I thought I should have.";
1125              return FALSE;
1126            }
1127          }
1128    
1129    // Check if the branch exists, otherwise fail        // Set the column positions as a variable for awk
1130    if (!file_exists($branch_location)) {        $column_variables = '';
1131      return "The branch '$branch' does not exist";        foreach ($column_positions as $position) {
1132    }          $column_variables .= "\ncolumns_to_change[$position] = $position\n";
1133          }
1134    
1135    // Ensure tmp directory exists        // Do the same for column positions of foreign keys with dependencies
1136    if (!file_exists($temp_location)) exec("mkdir -p $temp_location");        if (array_key_exists('foreign-key', $dependant_columns)) {
1137            $position = $dependant_columns['foreign-key']['position'];
1138            $column_variables .= "\ncolumn_with_dependency = $position\n";
1139            foreach ($dependant_columns['dependencies'] as $column_name => $values) {
1140              $position = $values['position'];
1141              $value = $values['value'];
1142              if (is_string($value)) {
1143                $column_variables .= "\ncolumn_dependency[$position] = \"'$value'\"\n";
1144              } else {
1145                $column_variables .= "\ncolumn_dependency[$position] = $value\n";
1146              }
1147            }
1148          }
1149    
1150    // Set the filtering options, ignoring tables not being tracked        // Write the column positions to a file for awk
1151    $tables_ignored = array();        exec("echo '#!/usr/bin/awk -f' > $temp_location/columns.awk");
1152    switch($filter_option){        exec("echo '{".$column_variables."}' >> $temp_location/columns.awk");
     case 'none':  
       break;  
1153    
1154      case 'min':        // Raise the increments in the csv version of the data
1155        $tables_ignored = array_merge($tables_filtered, $tables_filtered_l1);        foreach ($file_names as $file_name) {
1156        break;          exec("
1157                cat $temp_location/$file_name.csv | \\
1158                awk -f $script_path/helpers/csv.awk -f $temp_location/increment_pairs.awk -f $temp_location/columns.awk -f $script_path/helpers/change_column_values.awk | \\
1159                sed -e 's/,$//g' \\
1160                > $temp_location/$file_name-tmp.csv
1161            ");
1162    
1163            // Check if there were any errors
1164            if (exec("grep '^ERROR' $temp_location/$file_name-tmp.csv")) {
1165              print "ERROR: There was an error parsing the data in '$table_to_modify' as CSV.  Check the file '$temp_location/$file_name-tmp.csv'";
1166              return FALSE;
1167            } else {
1168              exec("mv $temp_location/$file_name-tmp.csv $temp_location/$file_name.csv");
1169            }
1170          }
1171    
1172      default:        // Delete variable temp file
1173        $tables_ignored = array_merge($tables_filtered, $tables_filtered_l1, $tables_filtered_l2);        exec("rm $temp_location/columns.awk");
       break;  
   }  
1174    
1175    // List of tables to check        // Convert the csv file back to SQL
1176    $table_list = _dbscripts_process_tables($branch, $tables_ignored);        foreach ($file_names as $file_name) {
1177    if (!is_array($table_list)) {          $sql = file("$branch_location/data/$file_name.sql", FILE_IGNORE_NEW_LINES);
     // Fail and pass through the message from _dbscripts_process_tables if it didn't pass an array  
     return $table_list;  
   }  
1178    
1179    // Get the id name of the table          // Get all the top sql comments
1180    $increment = dbscripts_get_table_increment($table, $branch);          $data_start = FALSE;
1181    if (!is_array($increment) && $increment != FALSE) {          foreach ($sql as $key => $line) {
1182      // If not FALSE and not an array, then fail and pass through the error message            if ($data_start === FALSE) {
1183          return $increment;              if (preg_match("/^INSERT INTO/", $line)){
1184    }                $data_start = $key;
1185    $id = isset($increment['id']) ? $increment['id'] : FALSE;              } else{
1186                  $line = str_replace("'", "#SQ#", $line); // issues with quotes
1187                  if ($key == 0) {
1188                    exec("echo '$line' > $temp_location/$file_name.sql");
1189                  } else {
1190                    exec("echo '$line' >> $temp_location/$file_name.sql");
1191                  }
1192                }
1193              }
1194            }
1195    
1196    $list = array();          // Reapply quotes to the top comments
1197    if ($id) {          exec("sed \"s/#SQ#/'/g\" $temp_location/$file_name.sql > $temp_location/$file_name-tmp.sql");
1198      foreach ($table_list as $check_table) {          exec("mv $temp_location/$file_name-tmp.sql $temp_location/$file_name.sql");
       // Ensure this table doesn't use the same ID name for auto increment as well  
       $match_increment = dbscripts_get_table_increment($check_table, $branch);  
       if (!is_array($match_increment) && $match_increment != FALSE) {  
         // If not FALSE and not an array, then fail and pass through the error message  
         return $match_increment;  
       }  
       $match_id = isset($match_increment['id']) ?  $match_increment['id'] : FALSE;  
1199    
1200          exec("grep '^  `' $branch_location/tables/$check_table.sql > $temp_location/columns.sql");          // Apply the new data after the top sql comments, converting the csv to sql along the way
1201        $columns = file("$temp_location/columns.sql", FILE_IGNORE_NEW_LINES);          exec("
1202        foreach ($columns as $column) {            sed -e 's/^/INSERT INTO `$table_to_modify` VALUES (/g' -e 's/$/);/g' \\
1203          $parts = explode('`', $column);            -e \"s/#BS#/\\\\\/g\" -e 's/#DQ#/\"/g' -e \"s/#SQ#/\\\\\'/g\" -e 's/#PND#/#/g' \\
1204          // Avoid returning columns that are auto_increment on that table            $temp_location/$file_name.csv >> $temp_location/$file_name.sql
1205          if (strpos($parts[1], $id) !== FALSE && $parts[1] != $match_id) {          ");
1206            $list[$check_table][] = $parts[1];  
1207            // Create a file of the bottom comments
1208            foreach ($sql as $key => $line) {
1209              if ($key > $data_start && !preg_match("/^INSERT INTO/", $line)) {
1210                $line = str_replace("'", "#SQ#", $line); // issues with quotes
1211                exec("echo '$line' >> $temp_location/$file_name-bottom.sql");
1212              }
1213          }          }
1214    
1215            // Reapply quotes to the bottom comments
1216            // (seperating sed statements to avoid running another sed query through the entire data)
1217            exec("sed \"s/#SQ#/'/g\" $temp_location/$file_name-bottom.sql > $temp_location/$file_name-tmp.sql");
1218    
1219            // Attach the bottom comments to the end of the sql file
1220            exec("cat $temp_location/$file_name-tmp.sql >> $temp_location/$file_name.sql");
1221    
1222            // Delete the temporary files
1223            exec("rm $temp_location/$file_name.csv");
1224            exec("rm $temp_location/$file_name-bottom.sql");
1225            exec("rm $temp_location/$file_name-tmp.sql");
1226        }        }
1227        exec("rm $temp_location/columns.sql");  
1228      }      }
1229    }    }
1230    
1231    return $list;    // Delete temporary file
1232      exec("rm $temp_location/increment_pairs.awk");
1233    
1234      // Since we got this far without error, we can now move
1235      // all the newly created sql files from temp back to the branch
1236      foreach ($table_references['references'] as $table_to_modify => $columns_referenced) {
1237        if (file_exists("$temp_location/$table_to_modify.sql")) {
1238          exec("mv $temp_location/$table_to_modify.sql $branch_location/data/$table_to_modify.sql");
1239        }
1240        if (file_exists("$temp_location/$table_to_modify-new.sql")) {
1241          exec("mv $temp_location/$table_to_modify-new.sql $branch_location/data/$table_to_modify-new.sql");
1242        }
1243      }
1244    
1245      return TRUE;
1246    
1247  }  }
1248    
1249    
1250    
1251  /**  /**
1252   * Return actual references to a given table   * Return actual references to a given table
1253   *   *
# Line 1283  function dbscripts_get_table_references( Line 1311  function dbscripts_get_table_references(
1311    
1312      // The table list file is important, so fail if it doesn't exist      // The table list file is important, so fail if it doesn't exist
1313      if (!file_exists("$branch_location/table_list.txt")) {      if (!file_exists("$branch_location/table_list.txt")) {
1314          return "The branch '$branch' does not have a table_list.txt file";        return "The branch '$branch' does not have a table_list.txt file";
1315      }      }
1316    
1317      $table_list = file("$branch_location/table_list.txt", FILE_IGNORE_NEW_LINES);      $table_list = file("$branch_location/table_list.txt", FILE_IGNORE_NEW_LINES);
# Line 1304  function dbscripts_get_table_references( Line 1332  function dbscripts_get_table_references(
1332            $wildcard = FALSE;            $wildcard = FALSE;
1333            if (is_array($config_references) && array_key_exists($check, $config_references) && is_array($config_references[$check])) {            if (is_array($config_references) && array_key_exists($check, $config_references) && is_array($config_references[$check])) {
1334              foreach ($config_references[$check] as $column) {              foreach ($config_references[$check] as $column) {
1335                if (strpos($column, '*') !== FALSE) {                if (!is_array($column) && strpos($column, '*') !== FALSE) {
1336                  $wildcard = TRUE;                  $wildcard = TRUE;
1337                }                }
1338              }              }
1339            }            }
1340            if (is_array($config_false_positive) && array_key_exists($check, $config_false_positive) && is_array($config_false_positive[$check])) {            if (is_array($config_false_positive) && array_key_exists($check, $config_false_positive) && is_array($config_false_positive[$check])) {
1341              foreach ($config_false_positive[$check] as $column) {              foreach ($config_false_positive[$check] as $column) {
1342                if (strpos($column, '*') !== FALSE) {                if (!is_array($column) && strpos($column, '*') !== FALSE) {
1343                  $wildcard = TRUE;                  $wildcard = TRUE;
1344                }                }
1345              }              }
# Line 1326  function dbscripts_get_table_references( Line 1354  function dbscripts_get_table_references(
1354              // Check each column              // Check each column
1355              foreach ($column_values as $column_value) {              foreach ($column_values as $column_value) {
1356                // Extract the column name                // Extract the column name
1357                  $column_value_parts = explode('`', $column_value);                $column_value_parts = explode('`', $column_value);
1358                $column_name = $column_value_parts[1];                $column_name = $column_value_parts[1];
1359    
1360                // Format other possible values for the column name                // Format other possible values for the column name
# Line 1354  function dbscripts_get_table_references( Line 1382  function dbscripts_get_table_references(
1382              exec("rm $temp_location/columns.sql");              exec("rm $temp_location/columns.sql");
1383    
1384            } else {            } else {
1385                  // Without a wildcard as the column name we can just return what was configured              // Without a wildcard as the column name we can just return what was configured
1386              if (isset($config_references[$check])) {              if (isset($config_references[$check])) {
1387                $references['references'][$check_table] = $config_references[$check];                $references['references'][$check_table] = $config_references[$check];
1388              }              }
# Line 1392  function dbscripts_get_table_references( Line 1420  function dbscripts_get_table_references(
1420            }            }
1421          }          }
1422        } else {        } else {
1423          // If an array is not returned, then pass through the error message          // If an array is not returned, then pass through the error message
1424          return $possible_references;          return $possible_references;
1425        }        }
1426      }      }
# Line 1412  function dbscripts_get_table_references( Line 1440  function dbscripts_get_table_references(
1440    
1441    
1442  /**  /**
1443   * Raise the increments, and its foreign keys, of the given table within the   * Get a given table's current auto increment value
  * given branch  
1444   *   *
1445   * @param $table   * @param $table
1446   *   Table to raise the increments of   *    The table name you want to check
  * @param $column  
  *   Column to raise the increments of  
  * @param $start_at  
  *   Range of increments within the table to start rewriting  
  * @param $change_to  
  *   Range to change rewrite the increments to.  Must be higher than both  
  *   $start_at, and the table's current increment value.  If it is not, then it  
  *   will be recalculated to be the highest value.  
1447   * @param $branch   * @param $branch
1448   *   Branch to make the changes on.   *    The branch that will be checked, since each branch could
1449     *    possibly have a different increment.
1450   */   */
1451  function dbscripts_raise_table_increments($table, $start_at, $change_to, $branch = 'development', $filter_option = 'full') {  function dbscripts_get_table_increment($table, $branch) {
1452    require('config.inc');    require('config.inc');
   require('config.references.inc');  
1453    
1454    // Ensure required files are loaded    // Ensure required files are loaded
1455    if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version.";    if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";
   if (!isset($tables_referenced)) return "The file 'config.references.inc' does not exist.  Copy from the example version.";  
1456    
   // Set locations  
1457    $branch_location = "$dump_path/$branch";    $branch_location = "$dump_path/$branch";
   $temp_location = "$dump_path/tmp";  
   
   // Ensure tmp directory exists  
   if (!file_exists($temp_location)) {  
      exec("mkdir -p $temp_location");  
   }  
1458    
1459    // Check if the branch exists, otherwise fail    // Check if the branch exists, otherwise fail
1460    if (!file_exists($branch_location)) {    if (!file_exists($branch_location)) {
1461      print "\n\nThe branch '$branch' does not exist\n\n";      return "The branch '$branch' does not exist";
     return FALSE;  
   }  
   
   // Check if the table exists, otherwise fail  
   if (!file_exists("$branch_location/tables/$table.sql")) {  
     print "\n\nThe table '$table' does not exist\n\n";  
     return FALSE;  
   }  
   
   // Find all tables that use the increment as a foreign key  
   $table_references = dbscripts_get_table_references($table, $branch, $filter_option);  
   if (!is_array($table_references)) {  
     print "\n\nERROR: ".$table_references."\n\n";  
     return FALSE;  
   }  
   
   // Fail if there are any found possible references  
   if (array_key_exists('found', $table_references)) {  
     print "\n\nFAILED:  Possible references found for table '$table'\n\n";  
     print_r($table_references['found']);  
     print "\nUpdate '$script_path/config.reference.inc' with this reference\n\n";  
     return FALSE;  
   }  
   
   // Add system path patterns as references  
   if (isset($system_paths[$table]['tables'])) {  
     foreach ($system_paths[$table]['tables'] as $system_path_table => $system_path_columns) {  
       foreach ($system_path_columns as $system_path_column) {  
         $table_references['references'][$system_path_table][] = $system_path_column;  
       }  
     }  
   }  
   
   // Find the largest increment value between $change_to and the current  
   // increment. Use the highest increment  
   $current_inc = dbscripts_get_table_increment($table, $branch);  
   if (is_array($current_inc) && $current_inc['num'] > $change_to) {  
     $change_to = $current_inc['num'];  
   }  
   
   // Get an array of the range of increments to work with  
   if ($start_at < $current_inc['num']) {  
     $increment_range = range($start_at, ($current_inc['num'] - 1));  
   } else {  
     // There is nothing to do then.  Likely there are no new records.  
     return TRUE;  
   }  
   
   // Create a key=>value array of increment pairs  
   $increment_pairs = array();  
   $increment_change = $change_to;  
   foreach ($increment_range as $increment) {  
     $increment_pairs[$increment] = $increment_change;  
     $increment_change++;  
1462    }    }
1463    
1464    // If there is a system paths reference, also add the pairs    $increment = FALSE;
1465    $pattern_pair_old = array();    if(file_exists("$branch_location/tables/$table.sql")) {
1466    $pattern_pair_new = array();      if (exec("grep 'auto_increment' $branch_location/tables/$table.sql")) {
1467    $fuzzy_pattern_pair_old = array();        $inc_string = exec("grep 'AUTO_INCREMENT=' $branch_location/tables/$table.sql");
   $fuzzy_pattern_pair_new = array();  
   if (isset($system_paths[$table])) {  
1468    
1469      // Exact patterns        $increment['num'] = '0';
1470      if (array_key_exists('patterns', $system_paths[$table])) {        if ($inc_string) {
1471        $i = 0;          $inc_string_parts = explode(' ', $inc_string);
1472        foreach ($system_paths[$table]['patterns'] as $key => $pattern) {          foreach ($inc_string_parts as $part) {
1473          foreach ($increment_pairs as $old_increment => $new_increment) {            if (strpos($part, 'AUTO_INCREMENT=') !== FALSE) {
1474            $pattern_pair_old[$i] = str_replace('*', $old_increment, $pattern);              $increment['num'] = str_replace('AUTO_INCREMENT=', '', $part);
1475            $pattern_pair_new[$i] = str_replace('*', $new_increment, $pattern);            }
           $i++;  
1476          }          }
1477        }        }
     }  
   
     // Fuzzy patterns  
     if (array_key_exists('fuzzy', $system_paths[$table])) {  
       $i = 0;  
       foreach($system_paths[$table]['fuzzy'] as $key => $pattern) {  
1478    
1479          $pattern_parts = explode('#', $pattern);        $id_string = exec("grep 'auto_increment' $branch_location/tables/$table.sql");
1480          $strlen_pattern = FALSE;        $id_string_parts = explode('`', $id_string);
1481          foreach ($pattern_parts as $part) {        $increment['id'] = $id_string_parts[1];
1482            if (strstr($part, 'NUMLEN+')) {      }
1483              $strlen_pattern = $part;    }
           }  
         }  
         $strlen = isset($strlen_pattern) ? str_replace('NUMLEN+', '', $strlen_pattern) : FALSE;  
1484    
1485          $pattern = str_replace(array('"', '\\'), array('#DQ#', '#BS#'), $pattern);    return $increment;
1486          //$pattern = str_replace('\\', '#BS', $pattern);  }
1487    
         foreach ($increment_pairs as $old_increment => $new_increment) {  
           $search = array();  
           $replace_old = array();  
           $replace_new = array();  
1488    
           $idlen_old = strlen($old_increment);  
           $idlen_new = strlen($new_increment);  
1489    
1490            $search[] = '*';  /**
1491            $replace_old[] = $old_increment;   * Return a table's primary key
1492            $replace_new[] = $new_increment;   *
1493     * @param $table
1494     *   Table to check
1495     * @param $branch
1496     *   Branch to check in
1497     */
1498    function dbscripts_get_table_primary_keys($table, $branch) {
1499      require('config.inc');
1500    
1501            $search[] = "#NUMLEN#";    // Ensure required files are loaded
1502            $replace_old[] = $idlen_old;    if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";
           $replace_new[] = $idlen_new;  
1503    
1504            if ($strlen) {    // Set locations
1505              $search[] = "#".$strlen_pattern."#";    $branch_location = "$dump_path/$branch";
             $replace_old[] = $strlen + $idlen_old;  
             $replace_new[] = $strlen + $idlen_new;  
           }  
1506    
1507            $fuzzy_pattern_pair_old[$i] = str_replace($search, $replace_old, $pattern);    if (file_exists("$branch_location/tables/$table.sql")) {
1508            $fuzzy_pattern_pair_new[$i] = str_replace($search, $replace_new, $pattern);      $primary_key_line = exec("grep '^  PRIMARY KEY' $branch_location/tables/$table.sql | sed 's/`//g'");
1509            $i++;      if ($primary_key_line) {
1510          }        $primary_key_line_parts = explode("(", $primary_key_line);
1511        }        $primary_key_line_parts = explode(")", $primary_key_line_parts[1]);
1512          $primary_keys = explode(",", $primary_key_line_parts[0]);
1513          return $primary_keys;
1514      }      }
   
1515    }    }
1516    
1517    // Write these increment and pattern pairs to a file for awk to use  }
   exec("echo '#!/usr/bin/awk -f' > $temp_location/increment_pairs.awk");  
   exec("echo '{' >> $temp_location/increment_pairs.awk");  
   foreach ($increment_pairs as $increment => $target) {  
     exec("echo 'increment_pairs[$increment] = $target' >> $temp_location/increment_pairs.awk");  
   }  
   if (array_key_exists('0', $pattern_pair_old)) {  
     foreach ($pattern_pair_old as $key => $pattern) {  
       exec("echo \"pattern_pair_old[$key] = \\\"'$pattern'\\\"\" >> $temp_location/increment_pairs.awk");  
     }  
     foreach ($pattern_pair_new as $key => $pattern) {  
       exec("echo \"pattern_pair_new[$key] = \\\"'$pattern'\\\"\" >> $temp_location/increment_pairs.awk");  
     }  
   }  
   if (array_key_exists('0', $fuzzy_pattern_pair_old)) {  
     foreach ($fuzzy_pattern_pair_old as $key => $pattern) {  
       exec("echo \"fuzzy_pattern_pair_old[$key] = \\\"$pattern\\\"\" >> $temp_location/increment_pairs.awk");  
     }  
     foreach ($fuzzy_pattern_pair_new as $key => $pattern) {  
       exec("echo \"fuzzy_pattern_pair_new[$key] = \\\"$pattern\\\"\" >> $temp_location/increment_pairs.awk");  
     }  
   }  
   exec("echo '}' >> $temp_location/increment_pairs.awk");  
1518    
1519    
   // Raise the auto_increment value of the table  
   exec("sed 's/ AUTO_INCREMENT={$current_inc['num']} / AUTO_INCREMENT={$increment_change} /g' $branch_location/tables/$table.sql > $temp_location/$table.sql");  
   exec("mv $temp_location/$table.sql $branch_location/tables/$table.sql");  
1520    
1521    // Raise the increment for all foreign keys of the given table  /**
1522    foreach ($table_references['references'] as $table_to_modify => $columns_referenced) {   * Find all possible references for the given table
1523     *
1524     * Helper script to make it easier to discover if there are possible references
1525     * to a given table.
1526     *
1527     * DOES NOT GAURANTEE TO FIND ALL REFERENCES
1528     * This is merely a tool to assist you in narrowing down possibilities and
1529     * provide a first level of error checking for dbscripts_get_table_references.
1530     * It is your responsibility to ensure all actual references are recorded in
1531     * config.references.inc
1532     *
1533     * @param $table
1534     *    Table to find all references of
1535     * @param $branch
1536     *    Branch to check
1537     * @param $filter_option
1538     *    What degree of filtering should be done on the tables returned, just
1539     *    like when dumping and restoring.
1540     */
1541    function dbscripts_find_possible_table_references($table, $branch, $filter_option = "full") {
1542      require('config.inc');
1543    
1544      // Check if this table exists and has any data stored    // Ensure required files are loaded
1545      if (    if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";
           file_exists("$branch_location/tables/$table_to_modify.sql") &&  
           (  
             file_exists("$branch_location/data/$table_to_modify.sql") ||  
             file_exists("$branch_location/data/$table_to_modify-new.sql")  
           )  
         ) {  
1546    
1547        // Create an array of the files we'll be working with (existing data and/or new data)    // Set locations
1548        $file_names = array();    $branch_location = "$dump_path/$branch";
1549        if (file_exists("$branch_location/data/$table_to_modify.sql")) {    $temp_location = "$dump_path/tmp";
         $file_names[] = $table_to_modify;  
       }  
       if (file_exists("$branch_location/data/$table_to_modify-new.sql")) {  
         $file_names[] = $table_to_modify."-new";  
       }  
1550    
1551        // Create a CSV version of the table's data    // Check if the branch exists, otherwise fail
1552        foreach ($file_names as $file_name) {    if (!file_exists($branch_location)) {
1553          exec("      return "The branch '$branch' does not exist";
1554              grep 'INSERT INTO' $branch_location/data/$file_name.sql \\    }
             |sed -e 's/^INSERT INTO `$table_to_modify` VALUES (//g' -e 's/);$//g' \\  
             |sed -e 's/#/#PND#/g' -e \"s/\\\\\'/#SQ#/g\" -e 's/\"/#DQ#/g' -e \"s/\\\\\/#BS#/g\" \\  
             > $temp_location/$file_name.csv  
         ");  
       }  
1555    
1556        // Create an array of the table's structure    // Ensure tmp directory exists
1557        exec("grep '^  `' $branch_location/tables/$table_to_modify.sql > $temp_location/$table_to_modify.txt");    if (!file_exists($temp_location)) exec("mkdir -p $temp_location");
       $table_columns = file("$temp_location/$table_to_modify.txt", FILE_IGNORE_NEW_LINES);  
       exec("rm $temp_location/$table_to_modify.txt");  
1558    
1559        // Find out the column position    // Set the filtering options, ignoring tables not being tracked
1560        $column_positions = array();    $tables_ignored = array();
1561        $dependant_columns = array();    switch($filter_option){
1562        foreach ($columns_referenced as $column_to_modify) {      case 'none':
1563          $found_position = FALSE;        break;
         foreach ($table_columns as $key => $table_column) { // the key defines the column's position  
1564    
1565            if (is_array($column_to_modify)) {      case 'min':
1566              // If the column_to_modify value is an array, it is a case that has dependencies        $tables_ignored = array_merge($tables_filtered, $tables_filtered_l1);
1567          break;
1568    
             // Restructure the array to something more useful, with the columns' positions  
             foreach ($column_to_modify as $column_name => $value) {  
               if (strpos($table_column, "`$column_name`")) {  
                 if ($value == '*') {  
                   $dependant_columns['foreign-key']['name'] = $column_name;  
                   $dependant_columns['foreign-key']['position'] = $key;  
                 } else {  
                   $dependant_columns['dependencies'][$column_name]['value'] = $value;  
                   $dependant_columns['dependencies'][$column_name]['position'] = $key;  
                 }  
                 $found_position = TRUE;  
               }  
             }  
1569    
1570            } else {      default:
1571              // but in most cases just have a single column value to find the position of        $tables_ignored = array_merge($tables_filtered, $tables_filtered_l1, $tables_filtered_l2);
1572              if (strpos($table_column, "`$column_to_modify`")) {        break;
1573                $column_positions[] = $key;    }
               $found_position = TRUE;  
             }  
           }  
1574    
1575          }    // List of tables to check
1576          if (!$found_position) {    $table_list = _dbscripts_process_tables($branch, $tables_ignored);
1577            print "ERROR: Didn't find column '$column_to_modify' in '$table_to_modify' when I thought I should have.";    if (!is_array($table_list)) {
1578            return FALSE;      // Fail and pass through the message from _dbscripts_process_tables if it didn't pass an array
1579          }      return $table_list;
1580        }    }
1581    
1582        // Set the column positions as a variable for awk    // Get the id name of the table
1583        $column_variables = '';    $increment = dbscripts_get_table_increment($table, $branch);
1584        foreach ($column_positions as $position) {    if (!is_array($increment) && $increment != FALSE) {
1585          $column_variables .= "\ncolumns_to_change[$position] = $position\n";      // If not FALSE and not an array, then fail and pass through the error message
1586        }      return $increment;
1587      }
1588      $id = isset($increment['id']) ? $increment['id'] : FALSE;
1589    
1590        // Do the same for column positions of foreign keys with dependencies    $list = array();
1591        if (array_key_exists('foreign-key', $dependant_columns)) {    if ($id) {
1592          $position = $dependant_columns['foreign-key']['position'];      foreach ($table_list as $check_table) {
1593          $column_variables .= "\ncolumn_with_dependency = $position\n";        // Ensure this table doesn't use the same ID name for auto increment as well
1594          foreach ($dependant_columns['dependencies'] as $column_name => $values) {        $match_increment = dbscripts_get_table_increment($check_table, $branch);
1595            $position = $values['position'];        if (!is_array($match_increment) && $match_increment != FALSE) {
1596            $value = $values['value'];          // If not FALSE and not an array, then fail and pass through the error message
1597            if (is_string($value)) {          return $match_increment;
             $column_variables .= "\ncolumn_dependency[$position] = \"'$value'\"\n";  
           } else {  
             $column_variables .= "\ncolumn_dependency[$position] = $value\n";  
           }  
         }  
1598        }        }
1599          $match_id = isset($match_increment['id']) ?  $match_increment['id'] : FALSE;
1600        // Write the column positions to a file for awk  
1601        exec("echo '#!/usr/bin/awk -f' > $temp_location/columns.awk");        exec("grep '^  `' $branch_location/tables/$check_table.sql > $temp_location/columns.sql");
1602        exec("echo '{".$column_variables."}' >> $temp_location/columns.awk");        $columns = file("$temp_location/columns.sql", FILE_IGNORE_NEW_LINES);
1603          foreach ($columns as $column) {
1604        // Raise the increments in the csv version of the data          $parts = explode('`', $column);
1605        foreach ($file_names as $file_name) {          // Avoid returning columns that are auto_increment on that table
1606          exec("          if (strpos($parts[1], $id) !== FALSE && $parts[1] != $match_id) {
1607              cat $temp_location/$file_name.csv | \\            $list[$check_table][] = $parts[1];
             awk -f $script_path/helpers/csv.awk -f $temp_location/increment_pairs.awk -f $temp_location/columns.awk -f $script_path/helpers/change_column_values.awk | \\  
             sed -e 's/,$//g' \\  
             > $temp_location/$file_name-tmp.csv  
         ");  
   
         // Check if there were any errors  
         if (exec("grep '^ERROR' $temp_location/$file_name-tmp.csv")) {  
           print "ERROR: There was an error parsing the data in '$table_to_modify' as CSV.  Check the file '$temp_location/$file_name-tmp.csv'";  
           return FALSE;  
         } else {  
           exec("mv $temp_location/$file_name-tmp.csv $temp_location/$file_name.csv");  
1608          }          }
1609        }        }
1610          exec("rm $temp_location/columns.sql");
1611        }
1612      }
1613    
1614        // Delete variable temp file    return $list;
1615        exec("rm $temp_location/columns.awk");  }
1616    
       // Convert the csv file back to SQL  
       foreach ($file_names as $file_name) {  
         $sql = file("$branch_location/data/$file_name.sql", FILE_IGNORE_NEW_LINES);  
1617    
         // Get all the top sql comments  
         $data_start = FALSE;  
         foreach ($sql as $key => $line) {  
           if ($data_start === FALSE) {  
             if (preg_match("/^INSERT INTO/", $line)){  
               $data_start = $key;  
             } else{  
               $line = str_replace("'", "#SQ#", $line); // issues with quotes  
               if ($key == 0) {  
                 exec("echo '$line' > $temp_location/$file_name.sql");  
               } else {  
                 exec("echo '$line' >> $temp_location/$file_name.sql");  
               }  
             }  
           }  
         }  
1618    
1619          // Reapply quotes to the top comments  /**
1620          exec("sed \"s/#SQ#/'/g\" $temp_location/$file_name.sql > $temp_location/$file_name-tmp.sql");   * Get a list of all tables that are using auto increment
1621          exec("mv $temp_location/$file_name-tmp.sql $temp_location/$file_name.sql");   *
1622     * @param $branch
1623     *    The branch that has the tables to check
1624     * @param $filter_option
1625     *    What degree of filtering should be done on the tables returned, just
1626     *    like when dumping and restoring.
1627     */
1628    function dbscripts_find_tables_with_increment($branch, $filter_option = "full") {
1629      require('config.inc');
1630    
1631          // Apply the new data after the top sql comments, converting the csv to sql along the way    // Ensure required files are loaded
1632          exec("    if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";
           sed -e 's/^/INSERT INTO `$table_to_modify` VALUES (/g' -e 's/$/);/g' \\  
           -e \"s/#BS#/\\\\\/g\" -e 's/#DQ#/\"/g' -e \"s/#SQ#/\\\\\'/g\" -e 's/#PND#/#/g' \\  
           $temp_location/$file_name.csv >> $temp_location/$file_name.sql  
         ");  
1633    
1634          // Create a file of the bottom comments    // Set location
1635          foreach ($sql as $key => $line) {    $branch_location = "$dump_path/$branch";
           if ($key > $data_start && !preg_match("/^INSERT INTO/", $line)) {  
             $line = str_replace("'", "#SQ#", $line); // issues with quotes  
             exec("echo '$line' >> $temp_location/$file_name-bottom.sql");  
           }  
         }  
1636    
1637          // Reapply quotes to the bottom comments    // Check if the branch exists, otherwise fail
1638          // (seperating sed statements to avoid running another sed query through the entire data)    if (!file_exists($branch_location)) {
1639          exec("sed \"s/#SQ#/'/g\" $temp_location/$file_name-bottom.sql > $temp_location/$file_name-tmp.sql");      return "The branch '$branch' does not exist";
1640      }
1641    
1642          // Attach the bottom comments to the end of the sql file    // Set the filtering options, ignoring tables not being tracked
1643          exec("cat $temp_location/$file_name-tmp.sql >> $temp_location/$file_name.sql");    $tables_ignored = array();
1644      switch($filter_option){
1645        case 'none':
1646          break;
1647    
1648          // Delete the temporary files      case 'min':
1649          exec("rm $temp_location/$file_name.csv");        $tables_ignored = array_merge($tables_filtered, $tables_filtered_l1);
1650          exec("rm $temp_location/$file_name-bottom.sql");        break;
         exec("rm $temp_location/$file_name-tmp.sql");  
       }  
1651    
1652      }      default:
1653          $tables_ignored = array_merge($tables_filtered, $tables_filtered_l1, $tables_filtered_l2);
1654          break;
1655    }    }
1656    
1657    // Delete temporary file    $table_list = _dbscripts_process_tables($branch, $tables_ignored);
1658    exec("rm $temp_location/increment_pairs.awk");    if (!is_array($table_list)) {
1659        // Fail and pass through the message from _dbscripts_process_tables if it didn't pass an array
1660        return $table_list;
1661      }
1662    
1663    // Since we got this far without error, we can now move    $list = array();
1664    // all the newly created sql files from temp back to the branch    foreach ($table_list as $table) {
1665    foreach ($table_references['references'] as $table_to_modify => $columns_referenced) {      $increment = dbscripts_get_table_increment($table, $branch);
1666      if (file_exists("$temp_location/$table_to_modify.sql")) {      if ($increment && is_array($increment)) {
1667        exec("mv $temp_location/$table_to_modify.sql $branch_location/data/$table_to_modify.sql");        $list[] = $table;
1668      }      } elseif ($increment != FALSE) {
1669      if (file_exists("$temp_location/$table_to_modify-new.sql")) {        // If not FALSE and not an array, then fail and pass through the error message
1670        exec("mv $temp_location/$table_to_modify-new.sql $branch_location/data/$table_to_modify-new.sql");          return $increment;
1671      }      }
1672    }    }
1673    
1674    return TRUE;    return $list;
   
1675  }  }
1676    
1677    
# Line 1872  function dbscripts_raise_all_increments( Line 1751  function dbscripts_raise_all_increments(
1751    
1752    
1753  /**  /**
1754     * Get the database connection settings from settings.php file
1755     *
1756     * Helper function for dump, erase and restore functions
1757     */
1758    function _dbscripts_db_connect() {
1759      require('config.inc');
1760      require("$settings_path");
1761    
1762      // Ensure required files are loaded
1763      if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";
1764      if (!isset($db_url)) return "The file 'settings.php' file does not exist.";
1765    
1766      preg_match('/'.$dbtype.':\/\/([^:]+):([^@]+)@([^\/]+)\/(.+)/', $db_url, $db_settings);
1767    
1768      if (empty($db_settings)) {
1769        return FALSE;
1770      } else {
1771    
1772        $dbuser = $db_settings[1];
1773        $dbpassword = $db_settings[2];
1774        $dbhost = $db_settings[3];
1775        $dbname = $db_settings[4];
1776    
1777        return "-u $dbuser -p$dbpassword -h $dbhost $dbname";
1778      }
1779    }
1780    
1781    
1782    
1783    /**
1784     * Get options for dump file and filtering
1785     *
1786     * Helper function for restore.php and dump.php
1787     *
1788     * @param $argv
1789     *   Pass in the $_SERVER['argv'] variable to return options set when running
1790     *   the script.
1791     */
1792    function _dbscripts_get_options($argv) {
1793      // Set default filter option
1794      $options['filter'] = 'full';
1795    
1796      // Set which branch to use
1797      $use_default_branch = FALSE;
1798      if(isset($argv[1])) {
1799        if(in_array($argv[1],array('min','none','full'))) {
1800          $use_default_branch = TRUE;
1801          $options['filter'] = $argv[1];
1802        }
1803      } else {
1804        $use_default_branch = TRUE;
1805      }
1806      $options['branch'] = $use_default_branch ? 'development' : $argv[1];
1807    
1808      // Set which last-merge to use
1809      $use_default_lastmerge = FALSE;
1810      if(isset($argv[2])) {
1811        if(in_array($argv[2],array('min','none','full'))) {
1812          $use_default_lastmerge = TRUE;
1813          $options['filter'] = $argv[2];
1814        }
1815      } else {
1816        $use_default_lastmerge = TRUE;
1817      }
1818      $options['last-merge'] = $use_default_lastmerge ? 'last-merge' : $argv[2];
1819    
1820      // Set filter option
1821      if(isset($argv[3])) {
1822        if(in_array($argv[3],array('min','none','full'))) {
1823          $options['filter'] = $argv[3];
1824        }
1825      }
1826    
1827      return $options;
1828    }
1829    
1830    
1831    
1832    /**
1833     * Process an array of tables
1834     *
1835     * When given an array of all tables, you can either remove matches
1836     * from the table list, or pick only positive matches
1837     *
1838     * @param $branch
1839     *    Which branch should be use for its list of tables
1840     * @param $tables_compare
1841     *    An array of table names that should be compared
1842     * @param $remove_match
1843     *    Should matches in $tables_compare be removed from the list, or kept
1844     */
1845    function _dbscripts_process_tables($branch, $tables_compare, $remove_match = TRUE) {
1846      require('config.inc');
1847    
1848      // Ensure required files are loaded
1849      if (!isset($dump_path)) return "The file 'config.inc' does not exist.  Copy from the example version?";
1850    
1851      // Set location
1852      $branch_location = "$dump_path/$branch";
1853    
1854      // Check if the branch exists, otherwise fail
1855      if (!file_exists($branch_location)) {
1856        return "The branch '$branch' does not exist";
1857      }
1858    
1859      // Check if the table list file exists, otherwise fail
1860      if (!file_exists("$branch_location/table_list.txt")) {
1861        return "The branch '$branch' does not have a table_list.txt file";
1862      }
1863    
1864      $tables = file("$branch_location/table_list.txt", FILE_IGNORE_NEW_LINES);
1865      $tables_match = array();
1866    
1867      foreach ($tables as $key => $table) {
1868        // Since some tables are specified with a .*, generating other possible values
1869        $truncated = explode('_', $table);
1870        $truncated1 = isset($truncated[0]) ? $truncated[0].'_.*' : '';
1871        $truncated2 = isset($truncated[1]) ? $truncated[0].'_'.$truncated[1].'_.*' : '';
1872    
1873        $check_tables = array($table, $truncated1, $truncated2);
1874        foreach ($check_tables as $check) {
1875          if (in_array($check, $tables_compare)) {
1876            $tables_match[$key] = $table;
1877          }
1878        }
1879      }
1880    
1881      foreach ($tables_match as $key => $table) {
1882        unset($tables[$key]);
1883      }
1884    
1885      if ($remove_match) {
1886        return $tables;
1887      } else {
1888        return $tables_match;
1889      }
1890    }
1891    
1892    
1893    
1894    /**
1895   * Return help for each script   * Return help for each script
1896   *   *
1897   * @param $script   * @param $script

Legend:
Removed from v.1.5.4.77  
changed lines
  Added in v.1.5.4.78

  ViewVC Help
Powered by ViewVC 1.1.2