From a49e6f533dcd6a026e7c4a6281e469c6e446ef91 Mon Sep 17 00:00:00 2001 From: Deven Bansod Date: Thu, 18 Jun 2015 23:32:31 +0530 Subject: [PATCH] Provide an option to export tables in a database as separate files Signed-off-by: Deven Bansod --- export.php | 39 ++++++-- js/export.js | 13 +++ libraries/display_export.lib.php | 34 +++++++ libraries/export.lib.php | 151 ++++++++++++++++++++++++------- 4 files changed, 198 insertions(+), 39 deletions(-) diff --git a/export.php b/export.php index 1a4e5cc346..f26bc65d2c 100644 --- a/export.php +++ b/export.php @@ -59,6 +59,7 @@ if (!defined('TESTSUITE')) { 'remember_template', 'charset_of_file', 'compression', + 'as_separate_files', 'knjenc', 'xkana', 'htmlword_structure_or_data', @@ -211,6 +212,7 @@ if (!defined('TESTSUITE')) { $file_handle = ''; $err_url = ''; $filename = ''; + $separate_files = ''; // Is it a quick or custom export? if ($_REQUEST['quick_or_custom'] == 'quick') { @@ -223,6 +225,16 @@ if (!defined('TESTSUITE')) { $asfile = false; } else { $asfile = true; + if (isset($_REQUEST['as_separate_files']) + && ! empty($_REQUEST['as_separate_files']) + ) { + if (isset($_REQUEST['compression']) + && ! empty($_REQUEST['compression']) + && $_REQUEST['compression'] == 'zip' + ) { + $separate_files = $_REQUEST['as_separate_files']; + } + } if (in_array($_REQUEST['compression'], $compression_methods)) { $compression = $_REQUEST['compression']; $buffer_needed = true; @@ -292,6 +304,9 @@ if (!defined('TESTSUITE')) { $dump_buffer = ''; $dump_buffer_len = 0; + // Array of dump_buffers - used in separate file exports + $dump_buffer_objects = array(); + // We send fake headers to avoid browser timeout when buffering $time_start = time(); @@ -380,9 +395,11 @@ if (!defined('TESTSUITE')) { // need exceptions here :-) do { - // Add possibly some comments to export - if (! $export_plugin->exportHeader($db)) { - break; + if ($separate_files != 'database') { + // Add possibly some comments to export + if (! $export_plugin->exportHeader($db)) { + break; + } } // Will we need relation & co. setup? @@ -412,7 +429,7 @@ if (!defined('TESTSUITE')) { PMA_exportServer( $db_select, $whatStrucOrData, $export_plugin, $crlf, $err_url, $export_type, $do_relation, $do_comments, $do_mime, $do_dates, - $aliases + $aliases, $separate_files ); } elseif ($export_type == 'database') { if (isset($lock_tables)) { @@ -421,7 +438,7 @@ if (!defined('TESTSUITE')) { PMA_exportDatabase( $db, $tables, $whatStrucOrData, $export_plugin, $crlf, $err_url, $export_type, $do_relation, $do_comments, - $do_mime, $do_dates, $aliases + $do_mime, $do_dates, $aliases, $separate_files ); PMA_unlockTables(); } catch (Exception $e) { // TODO use finally when PHP version is 5.5 @@ -432,7 +449,7 @@ if (!defined('TESTSUITE')) { PMA_exportDatabase( $db, $tables, $whatStrucOrData, $export_plugin, $crlf, $err_url, $export_type, $do_relation, $do_comments, $do_mime, $do_dates, - $aliases + $aliases, $separate_files ); } } else { @@ -495,8 +512,14 @@ if (!defined('TESTSUITE')) { // Compression needed? if ($compression) { - $dump_buffer - = PMA_compressExport($dump_buffer, $compression, $filename); + if (! empty($separate_files)) { + $dump_buffer + = PMA_compressExport($dump_buffer_objects, $compression, $filename); + } else { + $dump_buffer + = PMA_compressExport($dump_buffer, $compression, $filename); + } + } /* If we saved on server, we have to close file now */ diff --git a/js/export.js b/js/export.js index 265a5804a4..c97e72d94c 100644 --- a/js/export.js +++ b/js/export.js @@ -86,6 +86,19 @@ AJAX.registerOnload('export.js', function () { $("#checkbox_sql_auto_increment").removeProp('disabled').parent().fadeTo('fast', 1); } }); + + // For separate-file exports only ZIP compression is allowed + $('input[type="checkbox"][name="as_separate_files"]').change(function(){ + if (! $(this).attr('checked')) { + $('#compression').val('zip'); + } + }); + + $('#compression').change(function(){ + if ($('option:selected').val() !== 'zip') { + $('input[type="checkbox"][name="as_separate_files"]').attr('checked', false); + } + }); }); diff --git a/libraries/display_export.lib.php b/libraries/display_export.lib.php index d32ce84dfb..f9baf99779 100644 --- a/libraries/display_export.lib.php +++ b/libraries/display_export.lib.php @@ -628,6 +628,34 @@ function PMA_getHtmlForExportOptionsOutputRadio() return $html; } +/** + * Prints Html For Export Options Checkbox - Separate files + * + * @param String $export_type Selected Export Type + * + * @return string + */ +function PMA_getHtmlForExportOptionsOutputSeparateFiles($export_type) +{ + $html = '
  • '; + $html .= 'addFile( - $dump_buffer, - substr($filename, 0, -4) - ); + if (is_array($dump_buffer)) { + foreach ($dump_buffer as $table => $dump) { + $ext_pos = strpos($filename, '.'); + $extension = substr($filename, $ext_pos); + $zipfile->addFile( + $dump, + str_replace( + $extension, + '_' . $table . $extension, + $filename + ) + ); + } + } else { + $zipfile->addFile($dump_buffer, $filename); + } $dump_buffer = $zipfile->file(); } elseif ($compression == 'gzip' && PMA_gzencodeNeeded()) { // without the optional parameter level because it bugs @@ -417,6 +430,34 @@ function PMA_compressExport($dump_buffer, $compression, $filename) return $dump_buffer; } +/** + * Saves the dump_buffer for a particular table in an array + * Used in separate files export + * + * @param string $object_name the name of current object to be stored + * @param boolean $append optional boolean to append to an existing index or not + * + * @return void + */ +function PMA_saveObjectInBuffer($object_name, $append = false) +{ + + global $dump_buffer_objects, $dump_buffer, $dump_buffer_len; + + if (! empty($dump_buffer)) { + if ($append) { + $dump_buffer_objects[$object_name] .= $dump_buffer; + } else { + $dump_buffer_objects[$object_name] = $dump_buffer; + } + } + + // Re - initialize + $dump_buffer = ''; + $dump_buffer_len = 0; + +} + /** * Returns HTML containing the header for a displayed export * @@ -485,13 +526,14 @@ function PMA_getHtmlForDisplayedExportHeader($export_type, $db, $table) * @param bool $do_mime whether to add MIME info * @param bool $do_dates whether to add dates * @param array $aliases alias information for db/table/column + * @param string $separate_files whether it is a separate-files export * * @return void */ function PMA_exportServer( $db_select, $whatStrucOrData, $export_plugin, $crlf, $err_url, $export_type, $do_relation, $do_comments, $do_mime, $do_dates, - $aliases + $aliases, $separate_files ) { if (! empty($db_select)) { $tmp_select = implode($db_select, '|'); @@ -506,8 +548,11 @@ function PMA_exportServer( PMA_exportDatabase( $current_db, $tables, $whatStrucOrData, $export_plugin, $crlf, $err_url, $export_type, $do_relation, $do_comments, $do_mime, - $do_dates, $aliases + $do_dates, $aliases, $separate_files == 'database' ? $separate_files : '' ); + if ($separate_files == 'server') { + PMA_saveObjectInBuffer($current_db); + } } } // end foreach database } @@ -527,21 +572,26 @@ function PMA_exportServer( * @param bool $do_mime whether to add MIME info * @param bool $do_dates whether to add dates * @param array $aliases Alias information for db/table/column + * @param string $separate_files whether it is a separate-files export * * @return void */ function PMA_exportDatabase( $db, $tables, $whatStrucOrData, $export_plugin, $crlf, $err_url, $export_type, $do_relation, $do_comments, $do_mime, $do_dates, - $aliases + $aliases, $separate_files ) { $db_alias = !empty($aliases[$db]['alias']) ? $aliases[$db]['alias'] : ''; - if (! $export_plugin->exportDBHeader($db, $db_alias)) { - return; - } - if (! $export_plugin->exportDBCreate($db, $db_alias)) { - return; + + // If single file, add DB header and Create but don't store in $dump_buffer_objects + if (! $separate_files == 'database') { + if (! $export_plugin->exportDBHeader($db, $db_alias)) { + return; + } + if (! $export_plugin->exportDBCreate($db, $db_alias)) { + return; + } } if (method_exists($export_plugin, 'exportRoutines') @@ -551,7 +601,24 @@ function PMA_exportDatabase( ) !== false && isset($GLOBALS['sql_procedure_function']) ) { + if ($separate_files == 'database') { + if (! $export_plugin->exportHeader($db)) { + break; + } + if (! $export_plugin->exportDBHeader($db, $db_alias)) { + return; + } + if (! $export_plugin->exportDBCreate($db, $db_alias)) { + return; + } + PMA_saveObjectInBuffer('db'); + } + $export_plugin->exportRoutines($db, $aliases); + + if ($separate_files == 'database') { + PMA_saveObjectInBuffer('routines'); + } } $views = array(); @@ -567,20 +634,19 @@ function PMA_exportDatabase( || $whatStrucOrData == 'structure_and_data' ) { // for a view, export a stand-in definition of the table - // to resolve view dependencies - + // to resolve view dependencies (only when it's a single-file export) if ($is_view) { - - if (isset($GLOBALS['sql_create_view'])) { - if (! $export_plugin->exportStructure( - $db, $table, $crlf, $err_url, 'stand_in', - $export_type, $do_relation, $do_comments, - $do_mime, $do_dates, $aliases - )) { - break 1; + if ($separate_files == '') { + if (isset($GLOBALS['sql_create_view'])) { + if (! $export_plugin->exportStructure( + $db, $table, $crlf, $err_url, 'stand_in', + $export_type, $do_relation, $do_comments, + $do_mime, $do_dates, $aliases + )) { + break 1; + } } } - } else if (isset($GLOBALS['sql_create_table'])) { $table_size = $GLOBALS['maxsize']; @@ -625,6 +691,11 @@ function PMA_exportDatabase( break 1; } } + + // this buffer was filled, we save it and go to the next one + if ($separate_files == 'database') { + PMA_saveObjectInBuffer('tbl_' . $table); + } // now export the triggers (needs to be done after the data because // triggers can modify already imported tables) if (isset($GLOBALS['sql_create_trigger']) && ($whatStrucOrData == 'structure' @@ -637,7 +708,18 @@ function PMA_exportDatabase( )) { break 1; } + if ($separate_files == 'database') { + PMA_saveObjectInBuffer('triggers', true); + } } + + } + + if ($separate_files == 'database') { + if (! $export_plugin->exportDBFooter($db, $db_alias)) { + return; + } + PMA_saveObjectInBuffer('extra', true); } if (isset($GLOBALS['sql_create_view'])) { @@ -654,21 +736,28 @@ function PMA_exportDatabase( )) { break 1; } + if ($separate_files == 'database') { + PMA_saveObjectInBuffer('view_' . $view); + } } } } - if (! $export_plugin->exportDBFooter($db, $db_alias)) { - return; + if ($separate_files != 'database') { + // export metadata related to this db + if (isset($GLOBALS['sql_metadata'])) { + // Types of metadata to export. + // In the future these can be allowed to be selected by the user + $metadataTypes = PMA_getMetadataTypesToExport(); + $export_plugin->exportMetadata($db, $tables, $metadataTypes); + } } - // export metadata related to this db - if (isset($GLOBALS['sql_metadata'])) { - // Types of metadata to export. - // In the future these can be allowed to be selected by the user - $metadataTypes = PMA_getMetadataTypesToExport(); - $export_plugin->exportMetadata($db, $tables, $metadataTypes); + if ($separate_files != 'database') { + if (! $export_plugin->exportDBFooter($db, $db_alias)) { + return; + } } }