1. Added new backup/restore options for PostgreSQL 11. Fixes #3503
2. Ensure backup should work with '--data-only' and '--schema-only' for any format. Fixes #3347 3. Added supported "Dump Options" for "pg_dumpall" which was not there since pgAdmin 3. 4. Fixed issue where "--clean" should not clubbed with "--data-only" while taking backup. 5. Fixed "--oids" should not clubbed with "--inserts" or "--column-inserts" while taking backup.
@ -58,13 +58,15 @@ Click the *Dump options* tab to continue. Use the box fields in the *Dump option
|
||||
|
||||
* Move switches in the **Do not save** field box to select the objects that will not be included in the backup.
|
||||
|
||||
* Move the switch next to *Owner* to the *Yes* position to include commands that set object ownership.
|
||||
* Move the switch next to *Owner* to the *Yes* position to exclude commands that set object ownership.
|
||||
|
||||
* Move the switch next to *Privilege* to the *Yes* position to include commands that create access privileges.
|
||||
* Move the switch next to *Privilege* to the *Yes* position to exclude commands that create access privileges.
|
||||
|
||||
* Move the switch next to *Tablespace* to the *Yes* position to include tablespaces.
|
||||
* Move the switch next to *Tablespace* to the *Yes* position to exclude tablespaces.
|
||||
|
||||
* Move the switch next to *Unlogged table data* to the *Yes* position to include the contents of unlogged tables.
|
||||
* Move the switch next to *Unlogged table data* to the *Yes* position to exclude the contents of unlogged tables.
|
||||
|
||||
* Move the switch next to *Comments* to the *Yes* position to exclude commands that set the comments. **Note:** This option is visible only for database server greater than or equal to 11.
|
||||
|
||||
.. image:: images/backup_queries.png
|
||||
:alt: Queries option on backup dialog
|
||||
@ -79,6 +81,8 @@ Click the *Dump options* tab to continue. Use the box fields in the *Dump option
|
||||
|
||||
* Move the switch next to *Include DROP DATABASE statement* to the *Yes* position to include a command in the backup that will drop any existing database object with the same name before recreating the object during a backup.
|
||||
|
||||
* Move the switch next to *Load Via Partition Root* to the *Yes* position, so when dumping a COPY or INSERT statement for a partitioned table, target the root of the partitioning hierarchy which contains it rather than the partition itself. **Note:** This option is visible only for database server greater than or equal to 11.
|
||||
|
||||
.. image:: images/backup_disable.png
|
||||
:alt: Disable option on backup dialog
|
||||
|
||||
|
@ -12,12 +12,66 @@ Use the *Backup Server* dialog to create a plain-text script that will recreate
|
||||
Use the fields in the *General* tab to specify the following:
|
||||
|
||||
* Enter the name of the backup file in the *Filename* field. Optionally, select the *Browser* icon (ellipsis) to the right to navigate into a directory and select a file that will contain the archive.
|
||||
* Use the *Encoding* drop-down listbox to select the character encoding method that should be used for the archive. **Note:** This option is visible only for database server greater than or equal to 11.
|
||||
* Use the drop-down listbox next to *Role name* to specify a role with connection privileges on the selected server. The role will be used for authentication during the backup.
|
||||
|
||||
Move switches in the *Miscellaneous* box to specify the type of statements that should be included in the backup.
|
||||
.. image:: images/backup_server_objects.png
|
||||
:alt: Type of objects option on backup server dialog
|
||||
|
||||
* Move the *Verbose messages* switch to the *No* position to exclude status messages from the backup. The default is *Yes*.
|
||||
* Move the *Force double quote on identifiers* switch to the *Yes* position to name identifiers without changing case. The default is *No*.
|
||||
* Move switches in the **Type of objects** field box to specify details about the type of objects that will be backed up.
|
||||
|
||||
* Move the switch next to *Only data* to the *Yes* position to limit the back up to data.
|
||||
|
||||
* Move the switch next to *Only schema* to limit the back up to schema-level database objects.
|
||||
|
||||
.. image:: images/backup_server_do_not_save.png
|
||||
:alt: Do not save option on backup server dialog
|
||||
|
||||
* Move switches in the **Do not save** field box to select the objects that will not be included in the backup.
|
||||
|
||||
* Move the switch next to *Owner* to the *Yes* position to exclude commands that set object ownership.
|
||||
|
||||
* Move the switch next to *Privilege* to the *Yes* position to exclude commands that create access privileges.
|
||||
|
||||
* Move the switch next to *Tablespace* to the *Yes* position to exclude tablespaces.
|
||||
|
||||
* Move the switch next to *Unlogged table data* to the *Yes* position to exclude the contents of unlogged tables.
|
||||
|
||||
* Move the switch next to *Comments* to the *Yes* position to exclude commands that set the comments. **Note:** This option is visible only for database server greater than or equal to 11.
|
||||
|
||||
.. image:: images/backup_server_queries.png
|
||||
:alt: Queries option on backup server dialog
|
||||
|
||||
* Move switches in the **Queries** field box to specify the type of statements that should be included in the backup.
|
||||
|
||||
* Move the switch next to *Use Column Inserts* to the *Yes* position to dump the data in the form of INSERT statements and include explicit column names. Please note: this may make restoration from backup slow.
|
||||
|
||||
* Move the switch next to *Use Insert commands* to the *Yes* position to dump the data in the form of INSERT statements rather than using a COPY command. Please note: this may make restoration from backup slow.
|
||||
|
||||
* Move the switch next to *Include DROP DATABASE statement* to the *Yes* position to include a command in the backup that will drop any existing database object with the same name before recreating the object during a backup.
|
||||
|
||||
|
||||
.. image:: images/backup_server_disable.png
|
||||
:alt: Disable option on backup server dialog
|
||||
|
||||
* Move switches in the **Disable** field box to specify the type of statements that should be excluded from the backup.
|
||||
|
||||
* Move the switch next to *Trigger* (active when creating a data-only backup) to the *Yes* position to include commands that will disable triggers on the target table while the data is being loaded.
|
||||
|
||||
* Move the switch next to *$ quoting* to the *Yes* position to enable dollar quoting within function bodies; if disabled, the function body will be quoted using SQL standard string syntax.
|
||||
|
||||
.. image:: images/backup_server_miscellaneous.png
|
||||
:alt: Miscellaneous option on backup server dialog
|
||||
|
||||
* Move switches in the **Miscellaneous** field box to specify miscellaneous backup options.
|
||||
|
||||
* Move the switch next to *With OIDs* to the *Yes* position to include object identifiers as part of the table data for each table.
|
||||
|
||||
* Move the switch next to *Verbose messages* to the *No* position to instruct *pg_dump* to exclude verbose messages.
|
||||
|
||||
* Move the switch next to *Force double quotes on identifiers* to the *Yes* position to force the quoting of all identifiers.
|
||||
|
||||
* Move the switch next to *Use SET SESSION AUTHORIZATION* to the *Yes* position to include a statement that will use a SET SESSION AUTHORIZATION command to determine object ownership (instead of an ALTER OWNER command).
|
||||
|
||||
Click the *Backup* button to build and execute a command based on your selections; click the *Cancel* button to exit without saving work.
|
||||
|
||||
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 94 KiB |
BIN
docs/en_US/images/backup_server_disable.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
docs/en_US/images/backup_server_do_not_save.png
Normal file
After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 105 KiB |
BIN
docs/en_US/images/backup_server_miscellaneous.png
Normal file
After Width: | Height: | Size: 99 KiB |
BIN
docs/en_US/images/backup_server_objects.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
docs/en_US/images/backup_server_queries.png
Normal file
After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 114 KiB |
@ -10,6 +10,7 @@ This release contains a number of features and fixes reported since the release
|
||||
Features
|
||||
********
|
||||
|
||||
| `Feature #3503 <https://redmine.postgresql.org/issues/3503>`_ - Added new backup/restore options for PostgreSQL 11. Added dump options for 'pg_dumpall'.
|
||||
| `Feature #3553 <https://redmine.postgresql.org/issues/3553>`_ - Add a Spanish translation.
|
||||
|
||||
Bug fixes
|
||||
@ -17,6 +18,7 @@ Bug fixes
|
||||
|
||||
| `Bug #3136 <https://redmine.postgresql.org/issues/3136>`_ - Stabilise feature tests for continuous running on CI systems.
|
||||
| `Bug #3325 <https://redmine.postgresql.org/issues/3325>`_ - Fix sort/filter dialog issue where it incorrectly requires ASC/DESC.
|
||||
| `Bug #3347 <https://redmine.postgresql.org/issues/3347>`_ - Ensure backup should work with '--data-only' and '--schema-only' for any format.
|
||||
| `Bug #3407 <https://redmine.postgresql.org/issues/3407>`_ - Fix keyboard shortcuts layout in the preferences panel.
|
||||
| `Bug #3461 <https://redmine.postgresql.org/issues/3461>`_ - Ensure that refreshing a node also updates the Property list.
|
||||
| `Bug #3528 <https://redmine.postgresql.org/issues/3528>`_ - Handle connection errors properly in the query tool.
|
||||
|
@ -49,6 +49,8 @@ Click the *Restore options* tab to continue. Use the fields on the *Restore opti
|
||||
* Move the switch next to *Owner* to the *Yes* position to exclude commands that set object ownership.
|
||||
* Move the switch next to *Privilege* to the *Yes* position to exclude commands that create access privileges.
|
||||
* Move the switch next to *Tablespace* to the *Yes* position to exclude tablespaces.
|
||||
* Move the switch next to *Comments* to the *Yes* position to exclude commands that set the comments. **Note:** This option is visible only for database server greater than or equal to 11.
|
||||
|
||||
|
||||
.. image:: images/restore_queries.png
|
||||
:alt: Restore dialog queries section
|
||||
|
@ -259,117 +259,6 @@ def filename_with_file_manager_path(_file, create_file=True):
|
||||
@blueprint.route(
|
||||
'/job/<int:sid>', methods=['POST'], endpoint='create_server_job'
|
||||
)
|
||||
@login_required
|
||||
def create_backup_job(sid):
|
||||
"""
|
||||
Args:
|
||||
sid: Server ID
|
||||
|
||||
Creates a new job for backup task (Backup Server/Globals)
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
if request.form:
|
||||
# Convert ImmutableDict to dict
|
||||
data = dict(request.form)
|
||||
data = json.loads(data['data'][0], encoding='utf-8')
|
||||
else:
|
||||
data = json.loads(request.data, encoding='utf-8')
|
||||
|
||||
try:
|
||||
backup_file = filename_with_file_manager_path(data['file'])
|
||||
except Exception as e:
|
||||
return bad_request(errormsg=str(e))
|
||||
|
||||
# Fetch the server details like hostname, port, roles etc
|
||||
server = Server.query.filter_by(
|
||||
id=sid, user_id=current_user.id
|
||||
).first()
|
||||
|
||||
if server is None:
|
||||
return make_json_response(
|
||||
success=0,
|
||||
errormsg=_("Could not find the specified server.")
|
||||
)
|
||||
|
||||
# To fetch MetaData for the server
|
||||
from pgadmin.utils.driver import get_driver
|
||||
driver = get_driver(PG_DEFAULT_DRIVER)
|
||||
manager = driver.connection_manager(server.id)
|
||||
conn = manager.connection()
|
||||
connected = conn.connected()
|
||||
|
||||
if not connected:
|
||||
return make_json_response(
|
||||
success=0,
|
||||
errormsg=_("Please connect to the server first.")
|
||||
)
|
||||
|
||||
utility = manager.utility('backup_server')
|
||||
|
||||
args = [
|
||||
'--file',
|
||||
backup_file,
|
||||
'--host',
|
||||
manager.local_bind_host if manager.use_ssh_tunnel else server.host,
|
||||
'--port',
|
||||
str(manager.local_bind_port) if manager.use_ssh_tunnel
|
||||
else str(server.port),
|
||||
'--username',
|
||||
server.username,
|
||||
'--no-password',
|
||||
'--database',
|
||||
server.maintenance_db
|
||||
]
|
||||
|
||||
if 'role' in data and data['role']:
|
||||
args.append('--role')
|
||||
args.append(data['role'])
|
||||
if 'verbose' in data and data['verbose']:
|
||||
args.append('--verbose')
|
||||
if 'dqoute' in data and data['dqoute']:
|
||||
args.append('--quote-all-identifiers')
|
||||
if data['type'] == 'globals':
|
||||
args.append('--globals-only')
|
||||
|
||||
try:
|
||||
p = BatchProcess(
|
||||
desc=BackupMessage(
|
||||
BACKUP.SERVER if data['type'] != 'globals' else BACKUP.GLOBALS,
|
||||
sid,
|
||||
data['file'].encode('utf-8') if hasattr(
|
||||
data['file'], 'encode'
|
||||
) else data['file'],
|
||||
*args
|
||||
),
|
||||
cmd=utility, args=args
|
||||
)
|
||||
manager.export_password_env(p.id)
|
||||
# Check for connection timeout and if it is greater than 0 then
|
||||
# set the environment variable PGCONNECT_TIMEOUT.
|
||||
if manager.connect_timeout > 0:
|
||||
env = dict()
|
||||
env['PGCONNECT_TIMEOUT'] = str(manager.connect_timeout)
|
||||
p.set_env_variables(server, env=env)
|
||||
else:
|
||||
p.set_env_variables(server)
|
||||
|
||||
p.start()
|
||||
jid = p.id
|
||||
except Exception as e:
|
||||
current_app.logger.exception(e)
|
||||
return make_json_response(
|
||||
status=410,
|
||||
success=0,
|
||||
errormsg=str(e)
|
||||
)
|
||||
# Return response
|
||||
return make_json_response(
|
||||
data={'job_id': jid, 'success': 1}
|
||||
)
|
||||
|
||||
|
||||
@blueprint.route(
|
||||
'/job/<int:sid>/object', methods=['POST'], endpoint='create_object_job'
|
||||
)
|
||||
@ -392,12 +281,12 @@ def create_backup_objects_job(sid):
|
||||
else:
|
||||
data = json.loads(request.data, encoding='utf-8')
|
||||
|
||||
# Remove ratio from data in case of empty string
|
||||
if 'ratio' in data and data['ratio'] == '':
|
||||
data.pop("ratio")
|
||||
backup_obj_type = 'objects'
|
||||
if 'type' in data:
|
||||
backup_obj_type = data['type']
|
||||
|
||||
try:
|
||||
if data['format'] == 'directory':
|
||||
if 'format' in data and data['format'] == 'directory':
|
||||
backup_file = filename_with_file_manager_path(data['file'], False)
|
||||
else:
|
||||
backup_file = filename_with_file_manager_path(data['file'])
|
||||
@ -428,7 +317,9 @@ def create_backup_objects_job(sid):
|
||||
errormsg=_("Please connect to the server first.")
|
||||
)
|
||||
|
||||
utility = manager.utility('backup')
|
||||
utility = manager.utility('backup') if backup_obj_type == 'objects' \
|
||||
else manager.utility('backup_server')
|
||||
|
||||
args = [
|
||||
'--file',
|
||||
backup_file,
|
||||
@ -442,48 +333,53 @@ def create_backup_objects_job(sid):
|
||||
'--no-password'
|
||||
]
|
||||
|
||||
if backup_obj_type != 'objects':
|
||||
args.append('--database')
|
||||
args.append(server.maintenance_db)
|
||||
|
||||
if backup_obj_type == 'globals':
|
||||
args.append('--globals-only')
|
||||
|
||||
def set_param(key, param):
|
||||
if key in data and data[key]:
|
||||
args.append(param)
|
||||
|
||||
def set_value(key, param, value):
|
||||
if key in data:
|
||||
if value:
|
||||
if value is True and data[key]:
|
||||
args.append(param)
|
||||
args.append(data[key])
|
||||
else:
|
||||
args.append(param)
|
||||
args.append(value)
|
||||
def set_value(key, param, default_value=None):
|
||||
if key in data and data[key] is not None and data[key] != '':
|
||||
args.append(param)
|
||||
args.append(data[key])
|
||||
elif default_value is not None:
|
||||
args.append(param)
|
||||
args.append(default_value)
|
||||
|
||||
set_param('verbose', '--verbose')
|
||||
set_param('dqoute', '--quote-all-identifiers')
|
||||
set_value('role', '--role', True)
|
||||
if data['format'] is not None:
|
||||
set_value('role', '--role')
|
||||
|
||||
if backup_obj_type == 'objects' and \
|
||||
'format' in data and data['format'] is not None:
|
||||
if data['format'] == 'custom':
|
||||
args.extend(['--format=c'])
|
||||
|
||||
set_param('blobs', '--blobs')
|
||||
set_value('ratio', '--compress', True)
|
||||
|
||||
set_value('ratio', '--compress')
|
||||
elif data['format'] == 'tar':
|
||||
args.extend(['--format=t'])
|
||||
|
||||
set_param('blobs', '--blobs')
|
||||
|
||||
elif data['format'] == 'plain':
|
||||
args.extend(['--format=p'])
|
||||
if 'only_data' in data and data['only_data']:
|
||||
args.append('--data-only')
|
||||
set_param('disable_trigger', '--disable-triggers')
|
||||
else:
|
||||
set_param('only_schema', '--schema-only')
|
||||
set_param('dns_owner', '--no-owner')
|
||||
set_param('include_create_database', '--create')
|
||||
set_param('include_drop_database', '--clean')
|
||||
elif data['format'] == 'directory':
|
||||
args.extend(['--format=d'])
|
||||
|
||||
if 'only_data' in data and data['only_data']:
|
||||
set_param('only_data', '--data-only')
|
||||
if 'format' in data and data['format'] == 'plain':
|
||||
set_param('disable_trigger', '--disable-triggers')
|
||||
elif 'only_schema' in data and data['only_schema']:
|
||||
set_param('only_schema', '--schema-only')
|
||||
|
||||
set_param('dns_owner', '--no-owner')
|
||||
set_param('include_create_database', '--create')
|
||||
set_param('include_drop_database', '--clean')
|
||||
set_param('pre_data', '--section=pre-data')
|
||||
set_param('data', '--section=data')
|
||||
set_param('post_data', '--section=post-data')
|
||||
@ -496,31 +392,51 @@ def create_backup_objects_job(sid):
|
||||
set_param('with_oids', '--oids')
|
||||
set_param('use_set_session_auth', '--use-set-session-authorization')
|
||||
|
||||
set_value('encoding', '--encoding', True)
|
||||
set_value('no_of_jobs', '--jobs', True)
|
||||
if manager.version >= 110000:
|
||||
set_param('no_comments', '--no-comments')
|
||||
set_param('load_via_partition_root', '--load-via-partition-root')
|
||||
|
||||
for s in data['schemas']:
|
||||
args.extend(['--schema', s])
|
||||
set_value('encoding', '--encoding')
|
||||
set_value('no_of_jobs', '--jobs')
|
||||
|
||||
for s, t in data['tables']:
|
||||
args.extend([
|
||||
'--table', driver.qtIdent(conn, s, t)
|
||||
])
|
||||
if 'schemas' in data:
|
||||
for s in data['schemas']:
|
||||
args.extend(['--schema', s])
|
||||
|
||||
args.append(data['database'])
|
||||
if 'tables' in data:
|
||||
for s, t in data['tables']:
|
||||
args.extend([
|
||||
'--table', driver.qtIdent(conn, s, t)
|
||||
])
|
||||
|
||||
try:
|
||||
p = BatchProcess(
|
||||
desc=BackupMessage(
|
||||
BACKUP.OBJECT, sid,
|
||||
data['file'].encode('utf-8') if hasattr(
|
||||
data['file'], 'encode'
|
||||
) else data['file'],
|
||||
*args,
|
||||
database=data['database']
|
||||
),
|
||||
cmd=utility, args=args
|
||||
)
|
||||
if backup_obj_type == 'objects':
|
||||
args.append(data['database'])
|
||||
p = BatchProcess(
|
||||
desc=BackupMessage(
|
||||
BACKUP.OBJECT, sid,
|
||||
data['file'].encode('utf-8') if hasattr(
|
||||
data['file'], 'encode'
|
||||
) else data['file'],
|
||||
*args,
|
||||
database=data['database']
|
||||
),
|
||||
cmd=utility, args=args
|
||||
)
|
||||
else:
|
||||
p = BatchProcess(
|
||||
desc=BackupMessage(
|
||||
BACKUP.SERVER if backup_obj_type != 'globals'
|
||||
else BACKUP.GLOBALS,
|
||||
sid,
|
||||
data['file'].encode('utf-8') if hasattr(
|
||||
data['file'], 'encode'
|
||||
) else data['file'],
|
||||
*args
|
||||
),
|
||||
cmd=utility, args=args
|
||||
)
|
||||
|
||||
manager.export_password_env(p.id)
|
||||
# Check for connection timeout and if it is greater than 0 then
|
||||
# set the environment variable PGCONNECT_TIMEOUT.
|
||||
|
@ -62,7 +62,7 @@ define([
|
||||
dqoute: false,
|
||||
verbose: true,
|
||||
type: undefined,
|
||||
/* global, server */
|
||||
/* global */
|
||||
},
|
||||
schema: [{
|
||||
id: 'file',
|
||||
@ -97,22 +97,11 @@ define([
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous'),
|
||||
}],
|
||||
}, {
|
||||
id: 'server_note',
|
||||
label: gettext('Note'),
|
||||
text: gettext('The backup format will be PLAIN'),
|
||||
type: 'note',
|
||||
visible: function(m) {
|
||||
return m.get('type') === 'server';
|
||||
},
|
||||
}, {
|
||||
id: 'globals_note',
|
||||
label: gettext('Note'),
|
||||
text: gettext('Only objects global to the entire database will be backed up in PLAIN format'),
|
||||
type: 'note',
|
||||
visible: function(m) {
|
||||
return m.get('type') === 'globals';
|
||||
},
|
||||
}, {}],
|
||||
validate: function() {
|
||||
// TODO: HOW TO VALIDATE ???
|
||||
@ -183,6 +172,13 @@ define([
|
||||
value: 'directory',
|
||||
},
|
||||
],
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server') {
|
||||
setTimeout(function() { m.set('format', 'plain'); }, 10);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'ratio',
|
||||
label: gettext('Compression ratio'),
|
||||
@ -190,6 +186,11 @@ define([
|
||||
min: 0,
|
||||
max: 9,
|
||||
disabled: false,
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'encoding',
|
||||
label: gettext('Encoding'),
|
||||
@ -198,6 +199,15 @@ define([
|
||||
node: 'database',
|
||||
control: 'node-ajax-options',
|
||||
url: 'get_encodings',
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server') {
|
||||
var t = pgBrowser.tree,
|
||||
i = t.selected(),
|
||||
d = i && i.length == 1 ? t.itemData(i) : undefined;
|
||||
return d.version >= 110000;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'no_of_jobs',
|
||||
label: gettext('Number of jobs'),
|
||||
@ -206,6 +216,11 @@ define([
|
||||
disabled: function(m) {
|
||||
return !(m.get('format') === 'Directory');
|
||||
},
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'role',
|
||||
label: gettext('Role name'),
|
||||
@ -214,6 +229,14 @@ define([
|
||||
select2: {
|
||||
allowClear: false,
|
||||
},
|
||||
}, {
|
||||
id: 'server_note',
|
||||
label: gettext('Note'),
|
||||
text: gettext('The backup format will be PLAIN'),
|
||||
type: 'note',
|
||||
visible: function(m) {
|
||||
return m.get('type') === 'server';
|
||||
},
|
||||
}, {
|
||||
type: 'nested',
|
||||
control: 'fieldset',
|
||||
@ -250,6 +273,11 @@ define([
|
||||
m.get('only_schema');
|
||||
},
|
||||
}],
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
type: 'nested',
|
||||
control: 'fieldset',
|
||||
@ -285,6 +313,13 @@ define([
|
||||
control: Backform.CustomSwitchControl,
|
||||
disabled: false,
|
||||
group: gettext('Type of objects'),
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server') {
|
||||
setTimeout(function() { m.set('blobs', false); }, 10);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}],
|
||||
}, {
|
||||
type: 'nested',
|
||||
@ -315,6 +350,20 @@ define([
|
||||
control: Backform.CustomSwitchControl,
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
}, {
|
||||
id: 'no_comments',
|
||||
label: gettext('Comments'),
|
||||
control: Backform.CustomSwitchControl,
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
visible: function() {
|
||||
var t = pgBrowser.tree,
|
||||
i = t.selected(),
|
||||
d = i && i.length == 1 ? t.itemData(i) : undefined,
|
||||
s = pgBrowser.Nodes[d._type].getTreeNodeHierarchy(i)['server'];
|
||||
|
||||
return s.version >= 110000;
|
||||
},
|
||||
}],
|
||||
}, {
|
||||
type: 'nested',
|
||||
@ -339,12 +388,41 @@ define([
|
||||
control: Backform.CustomSwitchControl,
|
||||
disabled: false,
|
||||
group: gettext('Queries'),
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'include_drop_database',
|
||||
label: gettext('Include DROP DATABASE statement'),
|
||||
control: Backform.CustomSwitchControl,
|
||||
group: gettext('Queries'),
|
||||
deps: ['only_data'],
|
||||
disabled: function(m) {
|
||||
if (m.get('only_data')) {
|
||||
setTimeout(function() { m.set('include_drop_database', false); }, 10);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
id: 'load_via_partition_root',
|
||||
label: gettext('Load Via Partition Root'),
|
||||
control: Backform.CustomSwitchControl,
|
||||
disabled: false,
|
||||
group: gettext('Queries'),
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server')
|
||||
return false;
|
||||
|
||||
var t = pgBrowser.tree,
|
||||
i = t.selected(),
|
||||
d = i && i.length == 1 ? t.itemData(i) : undefined,
|
||||
s = pgBrowser.Nodes[d._type].getTreeNodeHierarchy(i)['server'];
|
||||
|
||||
return s.version >= 110000;
|
||||
},
|
||||
}],
|
||||
}, {
|
||||
type: 'nested',
|
||||
@ -376,8 +454,15 @@ define([
|
||||
id: 'with_oids',
|
||||
label: gettext('With OID(s)'),
|
||||
control: Backform.CustomSwitchControl,
|
||||
disabled: false,
|
||||
deps: ['use_column_inserts', 'use_insert_commands'],
|
||||
group: gettext('Miscellaneous'),
|
||||
disabled: function(m) {
|
||||
if (m.get('use_column_inserts') || m.get('use_insert_commands')) {
|
||||
setTimeout(function() { m.set('with_oids', false); }, 10);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
id: 'verbose',
|
||||
label: gettext('Verbose messages'),
|
||||
@ -483,33 +568,23 @@ define([
|
||||
return this;
|
||||
},
|
||||
start_backup_global: function(action, item) {
|
||||
var params = {
|
||||
'globals': true,
|
||||
};
|
||||
this.start_backup_global_server.apply(
|
||||
this, [action, item, params]
|
||||
);
|
||||
},
|
||||
start_backup_server: function(action, item) {
|
||||
var params = {
|
||||
'server': true,
|
||||
};
|
||||
this.start_backup_global_server.apply(
|
||||
this, [action, item, params]
|
||||
);
|
||||
},
|
||||
|
||||
// Callback to draw Backup Dialog for globals/server
|
||||
start_backup_global_server: function(action, treeItem, params) {
|
||||
let dialog = new globalBackupDialog.BackupDialog(
|
||||
pgBrowser,
|
||||
$,
|
||||
alertify,
|
||||
BackupModel
|
||||
);
|
||||
dialog.draw(action, treeItem, params);
|
||||
dialog.draw(action, item, {'globals': true});
|
||||
},
|
||||
start_backup_server: function(action, item) {
|
||||
let dialog = new globalBackupDialog.BackupDialog(
|
||||
pgBrowser,
|
||||
$,
|
||||
alertify,
|
||||
BackupObjectModel
|
||||
);
|
||||
dialog.draw(action, item, {'server': true});
|
||||
},
|
||||
|
||||
// Callback to draw Backup Dialog for objects
|
||||
backup_objects: function(action, treeItem) {
|
||||
let dialog = new globalBackupDialog.BackupDialog(
|
||||
|
@ -156,7 +156,7 @@ class BackupCreateJobTest(BaseTestGenerator):
|
||||
),
|
||||
url='/backup/job/{0}/object',
|
||||
expected_cmd_opts=['--verbose', '--format=p', '--data-only'],
|
||||
not_expected_cmd_opts=['--schema-only', '--no-owner'],
|
||||
not_expected_cmd_opts=['--schema-only'],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When backup the object with option only_schema',
|
||||
@ -240,6 +240,34 @@ class BackupCreateJobTest(BaseTestGenerator):
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When backup the object with option - Do not save comments,',
|
||||
dict(
|
||||
class_params=dict(
|
||||
sid=1,
|
||||
name='test_backup_server',
|
||||
port=5444,
|
||||
host='localhost',
|
||||
database='postgres',
|
||||
bfile='test_backup',
|
||||
username='postgres'
|
||||
),
|
||||
params=dict(
|
||||
file='test_backup_file',
|
||||
format='custom',
|
||||
verbose=True,
|
||||
schemas=[],
|
||||
tables=[],
|
||||
database='postgres',
|
||||
no_comments=True,
|
||||
),
|
||||
url='/backup/job/{0}/object',
|
||||
expected_cmd_opts=['--no-comments'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None],
|
||||
server_min_version=110000,
|
||||
message='Backup object with --no-comments are not supported '
|
||||
'by EPAS/PG server less than 11.0'
|
||||
)),
|
||||
('When backup the object with option - all queries',
|
||||
dict(
|
||||
class_params=dict(
|
||||
@ -269,6 +297,34 @@ class BackupCreateJobTest(BaseTestGenerator):
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When backup the object with option - load via partition root',
|
||||
dict(
|
||||
class_params=dict(
|
||||
sid=1,
|
||||
name='test_backup_server',
|
||||
port=5444,
|
||||
host='localhost',
|
||||
database='postgres',
|
||||
bfile='test_backup',
|
||||
username='postgres'
|
||||
),
|
||||
params=dict(
|
||||
file='test_backup_file',
|
||||
format='plain',
|
||||
verbose=True,
|
||||
schemas=[],
|
||||
tables=[],
|
||||
database='postgres',
|
||||
load_via_partition_root=True,
|
||||
),
|
||||
url='/backup/job/{0}/object',
|
||||
expected_cmd_opts=['--load-via-partition-root'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None],
|
||||
server_min_version=110000,
|
||||
message='Backup object with --load-via-partition-root are not '
|
||||
'supported by EPAS/PG server less than 11.0'
|
||||
)),
|
||||
('When backup the object with option - all queries and format custom',
|
||||
dict(
|
||||
class_params=dict(
|
||||
@ -293,9 +349,9 @@ class BackupCreateJobTest(BaseTestGenerator):
|
||||
include_drop_database=True
|
||||
),
|
||||
url='/backup/job/{0}/object',
|
||||
expected_cmd_opts=['--inserts',
|
||||
'--column-inserts'],
|
||||
not_expected_cmd_opts=['--create', '--clean'],
|
||||
expected_cmd_opts=['--inserts', '--clean',
|
||||
'--column-inserts', '--create'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When backup the object with option - miscellaneous',
|
||||
@ -355,6 +411,7 @@ class BackupCreateJobTest(BaseTestGenerator):
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
|
||||
('When backup the server',
|
||||
dict(
|
||||
class_params=dict(
|
||||
@ -377,6 +434,186 @@ class BackupCreateJobTest(BaseTestGenerator):
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When backup the server with option only_data',
|
||||
dict(
|
||||
class_params=dict(
|
||||
sid=1,
|
||||
name='test_backup_server',
|
||||
port=5444,
|
||||
host='localhost',
|
||||
database='postgres',
|
||||
bfile='test_backup',
|
||||
username='postgres'
|
||||
),
|
||||
params=dict(
|
||||
file='test_backup_server_file',
|
||||
type='server',
|
||||
verbose=True,
|
||||
only_data=True,
|
||||
only_schema=False
|
||||
),
|
||||
url='/backup/job/{0}',
|
||||
expected_cmd_opts=['--verbose', '--data-only'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When backup the server with option only_schema',
|
||||
dict(
|
||||
class_params=dict(
|
||||
sid=1,
|
||||
name='test_backup_server',
|
||||
port=5444,
|
||||
host='localhost',
|
||||
database='postgres',
|
||||
bfile='test_backup',
|
||||
username='postgres'
|
||||
),
|
||||
params=dict(
|
||||
file='test_backup_server_file',
|
||||
type='server',
|
||||
format='plain',
|
||||
verbose=True,
|
||||
only_data=False,
|
||||
only_schema=True
|
||||
),
|
||||
url='/backup/job/{0}',
|
||||
expected_cmd_opts=['--verbose', '--schema-only'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When backup the server with option - Do not save privilege,'
|
||||
' tablespace, unlogged table data',
|
||||
dict(
|
||||
class_params=dict(
|
||||
sid=1,
|
||||
name='test_backup_server',
|
||||
port=5444,
|
||||
host='localhost',
|
||||
database='postgres',
|
||||
bfile='test_backup',
|
||||
username='postgres'
|
||||
),
|
||||
params=dict(
|
||||
file='test_backup_server_file',
|
||||
type='server',
|
||||
format='plain',
|
||||
verbose=True,
|
||||
dns_privilege=True,
|
||||
dns_unlogged_tbl_data=True,
|
||||
dns_tablespace=True
|
||||
),
|
||||
url='/backup/job/{0}',
|
||||
expected_cmd_opts=['--no-privileges',
|
||||
'--no-tablespaces',
|
||||
'--no-unlogged-table-data'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When backup the server with option - Do not save comments,',
|
||||
dict(
|
||||
class_params=dict(
|
||||
sid=1,
|
||||
name='test_backup_server',
|
||||
port=5444,
|
||||
host='localhost',
|
||||
database='postgres',
|
||||
bfile='test_backup',
|
||||
username='postgres'
|
||||
),
|
||||
params=dict(
|
||||
file='test_backup_server_file',
|
||||
type='server',
|
||||
format='plain',
|
||||
verbose=True,
|
||||
no_comments=True,
|
||||
),
|
||||
url='/backup/job/{0}',
|
||||
expected_cmd_opts=['--no-comments'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None],
|
||||
server_min_version=110000,
|
||||
message='Backup server with --no-comments are not supported '
|
||||
'by EPAS/PG server less than 11.0'
|
||||
)),
|
||||
('When backup the server with option - all queries',
|
||||
dict(
|
||||
class_params=dict(
|
||||
sid=1,
|
||||
name='test_backup_server',
|
||||
port=5444,
|
||||
host='localhost',
|
||||
database='postgres',
|
||||
bfile='test_backup',
|
||||
username='postgres'
|
||||
),
|
||||
params=dict(
|
||||
file='test_backup_server_file',
|
||||
type='server',
|
||||
format='plain',
|
||||
verbose=True,
|
||||
use_column_inserts=True,
|
||||
use_insert_commands=True,
|
||||
include_drop_database=True
|
||||
),
|
||||
url='/backup/job/{0}',
|
||||
expected_cmd_opts=['--clean', '--inserts',
|
||||
'--column-inserts'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When backup the server with option - miscellaneous',
|
||||
dict(
|
||||
class_params=dict(
|
||||
sid=1,
|
||||
name='test_backup_server',
|
||||
port=5444,
|
||||
host='localhost',
|
||||
database='postgres',
|
||||
bfile='test_backup',
|
||||
username='postgres'
|
||||
),
|
||||
params=dict(
|
||||
file='test_backup_server_file',
|
||||
type='server',
|
||||
verbose=True,
|
||||
disable_quoting=True,
|
||||
use_set_session_auth=True,
|
||||
with_oids=True,
|
||||
dqoute=True
|
||||
),
|
||||
url='/backup/job/{0}',
|
||||
expected_cmd_opts=['--verbose', '--quote-all-identifiers',
|
||||
'--disable-dollar-quoting', '--oids',
|
||||
'--use-set-session-authorization'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When backup the server with encoding',
|
||||
dict(
|
||||
class_params=dict(
|
||||
sid=1,
|
||||
name='test_backup_server',
|
||||
port=5444,
|
||||
host='localhost',
|
||||
database='postgres',
|
||||
bfile='test_backup',
|
||||
username='postgres'
|
||||
),
|
||||
params=dict(
|
||||
file='test_backup_server_file',
|
||||
dqoute=False,
|
||||
verbose=True,
|
||||
type='server',
|
||||
encoding='UTF-8'
|
||||
),
|
||||
url='/backup/job/{0}',
|
||||
expected_cmd_opts=['--encoding'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None],
|
||||
server_min_version=110000,
|
||||
message='Backup server with encoding are not supported '
|
||||
'by EPAS/PG server less than 11.0'
|
||||
)),
|
||||
('When backup globals',
|
||||
dict(
|
||||
class_params=dict(
|
||||
@ -454,6 +691,11 @@ class BackupCreateJobTest(BaseTestGenerator):
|
||||
db_owner = server_response['data']['user']['name']
|
||||
self.data = database_utils.get_db_data(db_owner)
|
||||
|
||||
if hasattr(self, 'server_min_version') and \
|
||||
server_response["data"]["version"] < \
|
||||
self.server_min_version:
|
||||
self.skipTest(self.message)
|
||||
|
||||
url = self.url.format(self.server_id)
|
||||
|
||||
# Create the backup job
|
||||
|
@ -243,17 +243,13 @@ def create_restore_job(sid):
|
||||
return True
|
||||
return False
|
||||
|
||||
def set_value(key, param, value):
|
||||
if key in data:
|
||||
if value:
|
||||
if value is True and data[key]:
|
||||
args.append(param)
|
||||
args.append(data[key])
|
||||
else:
|
||||
args.append(param)
|
||||
args.append(value)
|
||||
return True
|
||||
return False
|
||||
def set_value(key, param, default_value=None):
|
||||
if key in data and data[key] is not None and data[key] != '':
|
||||
args.append(param)
|
||||
args.append(data[key])
|
||||
elif default_value is not None:
|
||||
args.append(param)
|
||||
args.append(default_value)
|
||||
|
||||
def set_multiple(key, param, with_schema=True):
|
||||
if key in data:
|
||||
@ -293,8 +289,8 @@ def create_restore_job(sid):
|
||||
'--username', server.username, '--no-password'
|
||||
])
|
||||
|
||||
set_value('role', '--role', True)
|
||||
set_value('database', '--dbname', True)
|
||||
set_value('role', '--role')
|
||||
set_value('database', '--dbname')
|
||||
|
||||
if data['format'] == 'directory':
|
||||
args.extend(['--format=d'])
|
||||
@ -318,7 +314,10 @@ def create_restore_job(sid):
|
||||
set_param('use_set_session_auth', '--use-set-session-authorization')
|
||||
set_param('exit_on_error', '--exit-on-error')
|
||||
|
||||
set_value('no_of_jobs', '--jobs', True)
|
||||
if manager.version >= 110000:
|
||||
set_param('no_comments', '--no-comments')
|
||||
|
||||
set_value('no_of_jobs', '--jobs')
|
||||
set_param('verbose', '--verbose')
|
||||
|
||||
set_multiple('schemas', '--schema', False)
|
||||
|
@ -240,6 +240,20 @@ commonUtils, menuUtils, supportedNodes, restoreDialog
|
||||
control: Backform.CustomSwitchControl,
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
}, {
|
||||
id: 'no_comments',
|
||||
label: gettext('Comments'),
|
||||
control: Backform.CustomSwitchControl,
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
visible: function() {
|
||||
var t = pgBrowser.tree,
|
||||
i = t.selected(),
|
||||
d = i && i.length == 1 ? t.itemData(i) : undefined,
|
||||
s = pgBrowser.Nodes[d._type].getTreeNodeHierarchy(i)['server'];
|
||||
|
||||
return s.version >= 110000;
|
||||
},
|
||||
}],
|
||||
}, {
|
||||
type: 'nested',
|
||||
|
@ -1,322 +0,0 @@
|
||||
diff a/web/pgadmin/tools/restore/static/js/restore.js b/web/pgadmin/tools/restore/static/js/restore.js (rejected hunks)
|
||||
@@ -391,318 +344,8 @@ commonUtils
|
||||
},
|
||||
// Callback to draw Backup Dialog for objects
|
||||
restore_objects: function(action, treeItem) {
|
||||
-
|
||||
- var i = treeItem || pgBrowser.tree.selected(),
|
||||
- server_data = null;
|
||||
-
|
||||
- while (i) {
|
||||
- var node_data = pgBrowser.tree.itemData(i);
|
||||
- if (node_data._type == 'server') {
|
||||
- server_data = node_data;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (pgBrowser.tree.hasParent(i)) {
|
||||
- i = $(pgBrowser.tree.parent(i));
|
||||
- } else {
|
||||
- alertify.alert(
|
||||
- gettext('Restore Error'),
|
||||
- gettext('Please select server or child node from tree.')
|
||||
- );
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (!server_data) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- var module = 'paths',
|
||||
- preference_name = 'pg_bin_dir',
|
||||
- msg = gettext('Please configure the PostgreSQL Binary Path in the Preferences dialog.');
|
||||
-
|
||||
- if ((server_data.type && server_data.type == 'ppas') ||
|
||||
- server_data.server_type == 'ppas') {
|
||||
- preference_name = 'ppas_bin_dir';
|
||||
- msg = gettext('Please configure the EDB Advanced Server Binary Path in the Preferences dialog.');
|
||||
- }
|
||||
-
|
||||
- var preference = pgBrowser.get_preference(module, preference_name);
|
||||
-
|
||||
- if (preference) {
|
||||
- if (!preference.value) {
|
||||
- alertify.alert(gettext('Configuration required'), msg);
|
||||
- return;
|
||||
- }
|
||||
- } else {
|
||||
- alertify.alert(
|
||||
- gettext('Restore Error'),
|
||||
- S(gettext('Failed to load preference %s of module %s')).sprintf(preference_name, module).value()
|
||||
- );
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- var title = S(gettext('Restore (%s: %s)')),
|
||||
- tree = pgBrowser.tree,
|
||||
- item = treeItem || tree.selected(),
|
||||
- data = item && item.length == 1 && tree.itemData(item),
|
||||
- node = data && data._type && pgBrowser.Nodes[data._type];
|
||||
-
|
||||
- if (!node)
|
||||
- return;
|
||||
-
|
||||
- var treeInfo = node.getTreeNodeHierarchy.apply(node, [item]);
|
||||
-
|
||||
- if (treeInfo.database._label.indexOf('=') >= 0) {
|
||||
- alertify.alert(
|
||||
- gettext('Restore error'),
|
||||
- gettext('Restore job creation failed. '+
|
||||
- 'Databases with = symbols in the name cannot be restored using this utility.')
|
||||
- );
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- title = title.sprintf(node.label, data.label).value();
|
||||
-
|
||||
- if (!alertify.pg_restore) {
|
||||
- // Create Dialog title on the fly with node details
|
||||
- alertify.dialog('pg_restore', function factory() {
|
||||
- return {
|
||||
- main: function(title, item, data, node) {
|
||||
- this.set('title', title);
|
||||
- this.setting('pg_node', node);
|
||||
- this.setting('pg_item', item);
|
||||
- this.setting('pg_item_data', data);
|
||||
- },
|
||||
- build: function() {
|
||||
- alertify.pgDialogBuild.apply(this);
|
||||
- },
|
||||
- setup: function() {
|
||||
- return {
|
||||
- buttons: [{
|
||||
- text: '',
|
||||
- className: 'btn btn-default pull-left fa fa-lg fa-info',
|
||||
- attrs: {
|
||||
- name: 'object_help',
|
||||
- type: 'button',
|
||||
- url: 'backup.html',
|
||||
- label: gettext('Restore'),
|
||||
- },
|
||||
- }, {
|
||||
- text: '',
|
||||
- key: 112,
|
||||
- className: 'btn btn-default pull-left fa fa-lg fa-question',
|
||||
- attrs: {
|
||||
- name: 'dialog_help',
|
||||
- type: 'button',
|
||||
- label: gettext('Restore'),
|
||||
- url: url_for('help.static', {
|
||||
- 'filename': 'restore_dialog.html',
|
||||
- }),
|
||||
- },
|
||||
- }, {
|
||||
- text: gettext('Restore'),
|
||||
- key: 13,
|
||||
- className: 'btn btn-primary fa fa-upload pg-alertify-button',
|
||||
- restore: true,
|
||||
- 'data-btn-name': 'restore',
|
||||
- }, {
|
||||
- text: gettext('Cancel'),
|
||||
- key: 27,
|
||||
- className: 'btn btn-danger fa fa-lg fa-times pg-alertify-button',
|
||||
- restore: false,
|
||||
- 'data-btn-name': 'cancel',
|
||||
- }],
|
||||
- // Set options for dialog
|
||||
- options: {
|
||||
- title: title,
|
||||
- //disable both padding and overflow control.
|
||||
- padding: !1,
|
||||
- overflow: !1,
|
||||
- model: 0,
|
||||
- resizable: true,
|
||||
- maximizable: true,
|
||||
- pinnable: false,
|
||||
- closableByDimmer: false,
|
||||
- modal: false,
|
||||
- },
|
||||
- };
|
||||
- },
|
||||
- hooks: {
|
||||
- // triggered when the dialog is closed
|
||||
- onclose: function() {
|
||||
- if (this.view) {
|
||||
- this.view.remove({
|
||||
- data: true,
|
||||
- internal: true,
|
||||
- silent: true,
|
||||
- });
|
||||
- }
|
||||
- },
|
||||
- },
|
||||
- settings: {
|
||||
- pg_node: null,
|
||||
- pg_item: null,
|
||||
- pg_item_data: null,
|
||||
- },
|
||||
- prepare: function() {
|
||||
-
|
||||
- var self = this;
|
||||
- // Disable Backup button until user provides Filename
|
||||
- this.__internal.buttons[2].element.disabled = true;
|
||||
- var $container = $('<div class=\'restore_dialog\'></div>');
|
||||
- var t = pgBrowser.tree,
|
||||
- i = t.selected(),
|
||||
- d = i && i.length == 1 ? t.itemData(i) : undefined,
|
||||
- node = d && pgBrowser.Nodes[d._type];
|
||||
-
|
||||
- if (!d)
|
||||
- return;
|
||||
-
|
||||
- var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]);
|
||||
-
|
||||
- var newModel = new RestoreObjectModel({
|
||||
- node_data: node,
|
||||
- }, {
|
||||
- node_info: treeInfo,
|
||||
- }),
|
||||
- fields = Backform.generateViewSchema(
|
||||
- treeInfo, newModel, 'create', node, treeInfo.server, true
|
||||
- );
|
||||
-
|
||||
- var view = this.view = new Backform.Dialog({
|
||||
- el: $container,
|
||||
- model: newModel,
|
||||
- schema: fields,
|
||||
- });
|
||||
-
|
||||
- $(this.elements.body.childNodes[0]).addClass(
|
||||
- 'alertify_tools_dialog_properties obj_properties'
|
||||
- );
|
||||
-
|
||||
- view.render();
|
||||
-
|
||||
- this.elements.content.appendChild($container.get(0));
|
||||
-
|
||||
- view.$el.attr('tabindex', -1);
|
||||
- // var dialogTabNavigator = pgBrowser.keyboardNavigation.getDialogTabNavigator(view);
|
||||
- pgBrowser.keyboardNavigation.getDialogTabNavigator(view);
|
||||
- var container = view.$el.find('.tab-content:first > .tab-pane.active:first');
|
||||
- commonUtils.findAndSetFocus(container);
|
||||
-
|
||||
- // Listen to model & if filename is provided then enable Backup button
|
||||
- this.view.model.on('change', function() {
|
||||
- if (!_.isUndefined(this.get('file')) && this.get('file') !== '') {
|
||||
- this.errorModel.clear();
|
||||
- self.__internal.buttons[2].element.disabled = false;
|
||||
- } else {
|
||||
- self.__internal.buttons[2].element.disabled = true;
|
||||
- this.errorModel.set('file', gettext('Please provide filename'));
|
||||
- }
|
||||
- });
|
||||
-
|
||||
- },
|
||||
- // Callback functions when click on the buttons of the Alertify dialogs
|
||||
- callback: function(e) {
|
||||
- // Fetch current server id
|
||||
- var t = pgBrowser.tree,
|
||||
- i = this.settings['pg_item'] || t.selected(),
|
||||
- d = this.settings['pg_item_data'] || (
|
||||
- i && i.length == 1 ? t.itemData(i) : undefined
|
||||
- ),
|
||||
- node = this.settings['pg_node'] || (
|
||||
- d && pgBrowser.Nodes[d._type]
|
||||
- );
|
||||
-
|
||||
- if (e.button.element.name == 'dialog_help' || e.button.element.name == 'object_help') {
|
||||
- e.cancel = true;
|
||||
- pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
|
||||
- node, i, e.button.element.getAttribute('label'));
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- if (e.button['data-btn-name'] === 'restore') {
|
||||
- if (!d)
|
||||
- return;
|
||||
-
|
||||
- var info = node.getTreeNodeHierarchy.apply(node, [i]),
|
||||
- m = this.view.model;
|
||||
- // Set current node info into model
|
||||
- m.set('database', info.database._label);
|
||||
- if (!m.get('custom')) {
|
||||
- switch (d._type) {
|
||||
- case 'schema':
|
||||
- m.set('schemas', [d._label]);
|
||||
- break;
|
||||
- case 'table':
|
||||
- m.set('schemas', [info.schema._label]);
|
||||
- m.set('tables', [d._label]);
|
||||
- break;
|
||||
- case 'function':
|
||||
- m.set('schemas', [info.schema._label]);
|
||||
- m.set('functions', [d._label]);
|
||||
- break;
|
||||
- case 'index':
|
||||
- m.set('schemas', [info.schema._label]);
|
||||
- m.set('indexes', [d._label]);
|
||||
- break;
|
||||
- case 'trigger':
|
||||
- m.set('schemas', [info.schema._label]);
|
||||
- m.set('triggers', [d._label]);
|
||||
- break;
|
||||
- case 'trigger_func':
|
||||
- m.set('schemas', [info.schema._label]);
|
||||
- m.set('trigger_funcs', [d._label]);
|
||||
- break;
|
||||
- }
|
||||
- } else {
|
||||
- // TODO::
|
||||
- // When we will implement the object selection in the
|
||||
- // import dialog, we will need to select the objects from
|
||||
- // the tree selection tab.
|
||||
- }
|
||||
-
|
||||
- var self = this,
|
||||
- baseUrl = url_for('restore.create_job', {
|
||||
- 'sid': info.server._id,
|
||||
- }),
|
||||
- args = this.view.model.toJSON();
|
||||
-
|
||||
- $.ajax({
|
||||
- url: baseUrl,
|
||||
- method: 'POST',
|
||||
- data: {
|
||||
- 'data': JSON.stringify(args),
|
||||
- },
|
||||
- success: function(res) {
|
||||
- if (res.success) {
|
||||
- alertify.success(
|
||||
- gettext('Restore job created.'), 5
|
||||
- );
|
||||
- pgBrowser.Events.trigger('pgadmin-bgprocess:created', self);
|
||||
- } else {
|
||||
- console.warn(res);
|
||||
- }
|
||||
- },
|
||||
- error: function(xhr) {
|
||||
- try {
|
||||
- var err = $.parseJSON(xhr.responseText);
|
||||
- alertify.alert(
|
||||
- gettext('Restore failed.'),
|
||||
- err.errormsg
|
||||
- );
|
||||
- } catch (e) {
|
||||
- console.warn(e.stack || e);
|
||||
- }
|
||||
- },
|
||||
- });
|
||||
- }
|
||||
- },
|
||||
- };
|
||||
- });
|
||||
- }
|
||||
-
|
||||
- alertify.pg_restore(title, item, data, node).resizeTo('65%', '60%');
|
||||
+ let dialog = new restoreDialog.RestoreDialog(pgBrowser, $, alertify, RestoreObjectModel);
|
||||
+ dialog.draw(action, treeItem);
|
||||
},
|
||||
};
|
||||
return pgBrowser.Restore;
|
@ -174,6 +174,36 @@ class RestoreCreateJobTest(BaseTestGenerator):
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None]
|
||||
)),
|
||||
('When restore object with option - Do not save comments',
|
||||
dict(
|
||||
class_params=dict(
|
||||
sid=1,
|
||||
name='test_restore_server',
|
||||
port=5444,
|
||||
host='localhost',
|
||||
database='postgres',
|
||||
bfile='test_restore',
|
||||
username='postgres'
|
||||
),
|
||||
params=dict(
|
||||
file='test_restore_file',
|
||||
format='custom',
|
||||
verbose=True,
|
||||
custom=False,
|
||||
schemas=[],
|
||||
tables=[],
|
||||
database='postgres',
|
||||
no_comments=True,
|
||||
only_data=False
|
||||
),
|
||||
url='/restore/job/{0}',
|
||||
expected_cmd_opts=['--no-comments'],
|
||||
not_expected_cmd_opts=[],
|
||||
expected_exit_code=[0, None],
|
||||
server_min_version=110000,
|
||||
message='Restore object with --no-comments are not supported '
|
||||
'by EPAS/PG server less than 11.0'
|
||||
)),
|
||||
('When restore object with option - Queries',
|
||||
dict(
|
||||
class_params=dict(
|
||||
@ -315,6 +345,11 @@ class RestoreCreateJobTest(BaseTestGenerator):
|
||||
self.data = database_utils.get_db_data(db_owner)
|
||||
self.db_name = self.data['name']
|
||||
|
||||
if hasattr(self, 'server_min_version') and \
|
||||
server_response["data"]["version"] < \
|
||||
self.server_min_version:
|
||||
self.skipTest(self.message)
|
||||
|
||||
url = self.url.format(self.server_id)
|
||||
|
||||
# Create the restore job
|
||||
|