database_mysql_dump.inc 5.5 KB
Newer Older
1 2 3
<?php
// $Id$

4 5 6 7 8
// Some older mysql client libs are missing this constant.
if (!defined('MYSQLI_BINARY_FLAG')) {
  define('MYSQLI_BINARY_FLAG', 128);
}

9 10 11
/**
 * Dump active database.
 */
smk-ka's avatar
smk-ka committed
12
function demo_dump_db($filename, $exclude = array()) {
13 14 15 16 17 18
  // Make sure we have permission to save our backup file.
  if (!file_check_directory(dirname($filename), FILE_CREATE_DIRECTORY)) {
    return FALSE;
  }

  if ($fp = fopen($filename, 'wb')) {
19
    $header  = "-- Demo.module database dump (version ". DEMO_DUMP_VERSION .")\n";
20 21
    $header .= "-- http://drupal.org/project/demo\n";
    $header .= "--\n";
22
    $header .= "-- Database: ". _demo_get_database() ."\n";
23
    $header .= "-- Date: ". format_date(time(), 'large') ."\n";
24 25 26
    fwrite($fp, $header);

    foreach (demo_enum_tables() as $table) {
27 28 29 30
      // Always export structure to allow creating a new site
      // from a database dump
      fwrite($fp, _demo_dump_table_structure($table));

smk-ka's avatar
smk-ka committed
31
      if (!in_array($table, $exclude)) {
32
        fwrite($fp, _demo_dump_table_data($table));
smk-ka's avatar
smk-ka committed
33
      }
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
    }

    fclose($fp);
    return TRUE;
  }

  return FALSE;
}

/**
 * Returns the name of the active database.
 */
function _demo_get_database() {
  $database = array_keys(db_fetch_array(db_query('SHOW TABLES')));
  $database = preg_replace('/^Tables_in_/', '', $database[0]);
  return $database;
}

/**
53
 * Dump table structure.
54
 */
55 56 57
function _demo_dump_table_structure($table) {
  $output  = "\n";
  $output .= "--\n";
58 59 60
  $output .= "-- Table structure for table '$table'\n";
  $output .= "--\n\n";

61 62 63 64 65
  $data = db_fetch_array(db_query("SHOW CREATE TABLE %s", $table));
  $output .= preg_replace('/^CREATE TABLE/', 'CREATE TABLE IF NOT EXISTS', $data['Create Table']) .";\n";

  return $output;
}
66

67 68 69 70 71 72 73
/**
 * Dump table data.
 *
 * This code has largely been stolen from the phpMyAdmin project.
 */
function _demo_dump_table_data($table) {
  $output  = "\n";
74 75 76 77
  $output .= "--\n";
  $output .= "-- Dumping data for table '$table'\n";
  $output .= "--\n\n";
  
smk-ka's avatar
smk-ka committed
78
  // Dump table data
79 80
  $result = db_query("SELECT * FROM %s", $table);

81 82
  // Get table fields.
  if ($fields = _demo_get_fields($result)) {
83 84 85
    // Disable indices to speed up import.
    $output .= "/*!40000 ALTER TABLE $table DISABLE KEYS */;\n";

smk-ka's avatar
smk-ka committed
86 87 88 89
    // Escape backslashes, PHP code, special chars
    $search = array('\\', "'", "\x00", "\x0a", "\x0d", "\x1a");
    $replace = array('\\\\', "''", '\0', '\n', '\r', '\Z');

90 91 92 93 94
    $insert_cmd = "INSERT INTO `$table` VALUES\n";
    $insert_buffer = '';
    $current_row = 0;
    $query_size = 0;

smk-ka's avatar
smk-ka committed
95
    while ($row = db_fetch_array($result)) {
96
      $current_row++;
smk-ka's avatar
smk-ka committed
97
      $values = array();
98
      $field = 0;
smk-ka's avatar
smk-ka committed
99 100 101 102
      foreach ($row as $value) {
        // NULL
        if (!isset($value) || is_null($value)) {
          $values[] = 'NULL';
103
        }
smk-ka's avatar
smk-ka committed
104 105
        // A number
        // timestamp is numeric on some MySQL 4.1, BLOBs are sometimes numeric
106
        else if ($fields[$field]->numeric && !$fields[$field]->timestamp && !$fields[$field]->blob) {
smk-ka's avatar
smk-ka committed
107 108
          $values[] = $value;
        }
109 110 111 112 113 114 115
        // A true BLOB
        // - mysqldump only generates hex data when the --hex-blob
        //   option is used, for fields having the binary attribute
        //   no hex is generated
        // - a TEXT field returns type blob but a real blob
        //   returns also the 'binary' flag
        else if ($fields[$field]->binary && $fields[$field]->blob) {
smk-ka's avatar
smk-ka committed
116 117 118 119 120 121 122 123 124 125 126
          // Empty blobs need to be different, but '0' is also empty :-(
          if (empty($value) && $value != '0') {
              $values[] = "''";
          } else {
              $values[] = '0x' . bin2hex($value);
          }
        }
        // Something else -> treat as a string
        else {
          $values[] = "'". str_replace($search, $replace, $value) ."'";
        }
127 128 129 130 131 132 133 134 135 136 137 138 139 140
        $field++;
      }

      if ($current_row == 1) {
        $insert_buffer = $insert_cmd . '('. implode(', ', $values) . ')';
      }
      else {
        $insert_buffer = '('. implode(', ', $values) . ')';
        if ($query_size + strlen($insert_buffer) > 50000) {
          $output .= ";\n";
          $current_row = 1;
          $query_size = 0;
          $insert_buffer = $insert_cmd . $insert_buffer;
        }
141
      }
142 143 144
      $query_size += strlen($insert_buffer);

      $output .= ($current_row == 1 ? '' : ",\n") . $insert_buffer;
145
    }
smk-ka's avatar
smk-ka committed
146

147 148 149
    if ($current_row > 0) {
      $output .= ";\n";
    }
150 151 152

    // Enable indices again.
    $output .= "/*!40000 ALTER TABLE $table ENABLE KEYS */;\n";
153
  }
smk-ka's avatar
smk-ka committed
154

155 156 157 158 159 160 161 162
  return $output;
}

/**
 * Return table fields and their properties.
 */
function _demo_get_fields($result) {
  $fields = array();
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

  switch ($GLOBALS['db_type']) {
    case 'mysql':
      $num_fields = mysql_num_fields($result);
      for ($i = 0; $i < $num_fields; $i++) {
        $meta = mysql_fetch_field($result, $i);
        // Enhance field definition with custom properties.
        $meta->timestamp = (int)($meta->type == 'timestamp');
        $flags = mysql_field_flags($result, $i);
        $meta->binary = (int)(stristr($flags, 'binary') !== FALSE);
        $fields[] = $meta;
      }
      break;

    case 'mysqli':
      while ($meta = mysqli_fetch_field($result)) {
        // Enhance the field definition for mysql-extension compatibilty.
        $meta->numeric = (int)(bool)($meta->flags & MYSQLI_NUM_FLAG);
        $meta->blob = (int)(bool)($meta->flags & MYSQLI_BLOB_FLAG);
        // Add custom properties.
        $meta->timestamp = (int)($meta->type == MYSQLI_TYPE_TIMESTAMP);
        $meta->binary = (int)(bool)($meta->flags & MYSQLI_BINARY_FLAG);
        $fields[] = $meta;
      }
      break;
188
  }
189

190 191 192
  return $fields;
}