From 9aa116bf3f8bdb712d1ee7f26a8f3ae72aa8b312 Mon Sep 17 00:00:00 2001 From: Akshay Joshi Date: Mon, 10 Jul 2023 10:34:30 +0530 Subject: [PATCH] 1) Added new/missing parameters to pg_dumpall (Backup Server). #6416 2) Added new/missing parameters to pg_dump (Backup Objects). #6417 --- docs/en_US/backup_dialog.rst | 88 ++- docs/en_US/backup_server_dialog.rst | 106 +++- docs/en_US/release_notes_7_5.rst | 3 +- web/pgadmin/tools/backup/__init__.py | 114 ++-- web/pgadmin/tools/backup/static/js/backup.js | 5 +- .../tools/backup/static/js/backup.ui.js | 387 +++++++++---- .../tests/test_backup_create_job_unit_test.py | 540 ++++++++++++++++-- web/pgadmin/tools/sqleditor/command.py | 1 - 8 files changed, 981 insertions(+), 263 deletions(-) diff --git a/docs/en_US/backup_dialog.rst b/docs/en_US/backup_dialog.rst index ed9c43a65..78329c639 100644 --- a/docs/en_US/backup_dialog.rst +++ b/docs/en_US/backup_dialog.rst @@ -67,7 +67,7 @@ Use the fields in the *General* tab to specify parameters for the backup: * Use the dropdown listbox next to *Rolename* to specify the role that owns the backup. -Click the *Data/Objects* tab to continue. Use the fields in the *Data/Objects* +Click the *Data Options* tab to continue. Use the fields in the *Data Options* tab to provide options related to data or pgAdmin objects that correspond to *pg_dump*. .. image:: images/backup_sections.png @@ -97,7 +97,7 @@ tab to provide options related to data or pgAdmin objects that correspond to *pg * Move the switch next to *Only data* towards right position to limit the back up to data. - * Move the switch next to *Only schema* to limit the back up to schema-level + * Move the switch next to *Only schemas* to limit the back up to schema-level database objects. * Move the switch next to *Blobs* towards left position to exclude large @@ -113,10 +113,10 @@ tab to provide options related to data or pgAdmin objects that correspond to *pg * Move the switch next to *Owner* towards right position to exclude commands that set object ownership. - * Move the switch next to *Privilege* towards right position to exclude + * Move the switch next to *Privileges* towards right position to exclude commands that create access privileges. - * Move the switch next to *Tablespace* towards right position to exclude + * Move the switch next to *Tablespaces* towards right position to exclude tablespaces. * Move the switch next to *Unlogged table data* towards right position to @@ -126,25 +126,45 @@ tab to provide options related to data or pgAdmin objects that correspond to *pg commands that set the comments. **Note:** This option is visible only for database server greater than or equal to 11. -Click the *Options* tab to continue. Use these additional fields to specify -options like including ddl statements, verbose message or using set session -authorization corresponding to *pg_dump* options. + * Move the switch next to *Publications* towards right position to exclude + publications. + + * Move the switch next to *Subscriptions* towards right position to exclude + subscriptions. + + * Move the switch next to *Security labels* towards right position to exclude + Security labels. + + * Move the switch next to *Toast compressions* towards right position to exclude + Toast compressions. **Note:** This option is visible only for + database server greater than or equal to 14. + + * Move the switch next to *Table access methods* towards right position to exclude + Table access methods. **Note:** This option is visible only for + database server greater than or equal to 15. .. image:: images/backup_queries.png :alt: Queries option on backup dialog :align: center -* Move switches in the **Queries** field box to specify the type of statements - that should be included in the backup. +Click the *Query Options* tab to continue. Use these additional fields to specify +the type of statements that should be included in the backup. - * Move the switch next to *Use Column Inserts* towards right 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* towards right position to + * Move the switch next to *Use INSERT commands* towards right 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. + * Use the *Maximum rows per INSERT command* field to controls the maximum + number of rows per INSERT command. **Note:** This option is visible only for + database server greater than or equal to 12. + + * Move the switch next to *On conflict do nothing to INSERT command* towards + right position to add ON CONFLICT DO NOTHING to INSERT command. + This option is not valid unless *Use INSERT commands*, *Use Column INSERTS* + or *Maximum rows per INSERT command* is also specified. + **Note:** This option is visible only for database server greater than or + equal to 12. + * Move the switch next to *Include CREATE DATABASE statement* towards right position to include a command in the backup that creates a new database when restoring the backup. @@ -154,12 +174,38 @@ authorization corresponding to *pg_dump* options. database object with the same name before recreating the object during a backup. - * Move the switch next to *Load Via Partition Root* towards right position, + * Move the switch next to *Include IF EXISTS clause* towards right + position to add an IF EXISTS clause to drop databases and other objects. + This option is not valid unless *Include DROP DATABASE statement* is also set. + + +Click the *Table Options* tab to continue. Use the fields in the *Table Options* +tab related to tables that should be included in the backup. + + * Move the switch next to *Use Column INSERTS* towards right 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 *Load via partition root* towards right 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. + * Move the switch next to *Enable row security* towards right position to + set row_security to on instead, allowing the user to dump the parts of the + contents of the table that they have access to. This option is relevant + only when dumping the contents of a table which has row security. + + * Move the switch next to *With OIDs* towards right position to include object + identifiers as part of the table data for each table. + + * Use the *Exclude table data* field to not dump data for any tables + matching the table pattern. + +Click the *Options* tab to continue. Use the fields in the *Options* +tab to provide other backup options. + .. image:: images/backup_disable.png :alt: Disable option on backup dialog :align: center @@ -182,9 +228,6 @@ authorization corresponding to *pg_dump* options. * Move switches in the **Miscellaneous** field box to specify miscellaneous backup options. - * Move the switch next to *With OIDs* towards right position to include object - identifiers as part of the table data for each table. - * Move the switch next to *Verbose messages* towards left position to instruct *pg_dump* to exclude verbose messages. @@ -195,6 +238,13 @@ authorization corresponding to *pg_dump* options. position to include a statement that will use a SET SESSION AUTHORIZATION command to determine object ownership (instead of an ALTER OWNER command). + * Use the *Extra float digits* field to use the specified value when dumping + floating-point data, instead of the maximum available precision. + + * Use the *Lock wait timeout* field to do not wait forever to acquire shared + table locks at the beginning of the dump. Instead, fail if unable to lock a + table within the specified timeout. + When you’ve specified the details that will be incorporated into the pg_dump command: @@ -205,4 +255,4 @@ command: pgAdmin will run the backup process in background. You can view all the background process with there running status and logs on the :ref:`Processes ` -tab \ No newline at end of file +tab diff --git a/docs/en_US/backup_server_dialog.rst b/docs/en_US/backup_server_dialog.rst index 7761d8886..9ecb52e2e 100644 --- a/docs/en_US/backup_server_dialog.rst +++ b/docs/en_US/backup_server_dialog.rst @@ -24,22 +24,27 @@ Use the fields in the *General* tab to specify the following: connection privileges on the selected server. The role will be used for authentication during the backup. +Click the *Data Options* tab to continue. Use the fields in the *Data Options* +tab to provide options related to data or pgAdmin objects that correspond to *pg_dumpall*. + .. image:: images/backup_server_objects.png :alt: Type of objects option on backup server dialog :align: center -Click the *Data/Objects* tab to continue. Use the fields in the *Data/Objects* -tab to provide options related to data or pgAdmin objects that correspond to *pg_dump*. - * 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* towards right position to limit the back up to data. - * Move the switch next to *Only schema* to limit the back up to schema-level + * Move the switch next to *Only schemas* to limit the back up to schema-level database objects. + * Move the switch next to *Only tablespaces* to limit the back + up to tablespaces only. + + * Move the switch next to *Only roles* to limit the back up to roles only. + .. image:: images/backup_server_do_not_save.png :alt: Do not save option on backup server dialog :align: center @@ -50,10 +55,13 @@ tab to provide options related to data or pgAdmin objects that correspond to *pg * Move the switch next to *Owner* towards right position to exclude commands that set object ownership. - * Move the switch next to *Privilege* towards right position to exclude + * Move the switch next to *Role passwords* towards right position to exclude + passwords for roles. + + * Move the switch next to *Privileges* towards right position to exclude commands that create access privileges. - * Move the switch next to *Tablespace* towards right position to exclude + * Move the switch next to *Tablespaces* towards right position to exclude tablespaces. * Move the switch next to *Unlogged table data* towards right position to @@ -63,26 +71,73 @@ tab to provide options related to data or pgAdmin objects that correspond to *pg commands that set the comments. **Note:** This option is visible only for database server greater than or equal to 11. + * Move the switch next to *Publications* towards right position to exclude + publications. + + * Move the switch next to *Subscriptions* towards right position to exclude + subscriptions. + + * Move the switch next to *Security labels* towards right position to exclude + Security labels. + + * Move the switch next to *Toast compressions* towards right position to exclude + Toast compressions. **Note:** This option is visible only for + database server greater than or equal to 14. + + * Move the switch next to *Table access methods* towards right position to exclude + Table access methods. **Note:** This option is visible only for + database server greater than or equal to 15. + .. image:: images/backup_server_queries.png :alt: Queries option on backup server dialog :align: center -* Move switches in the **Queries** field box to specify the type of statements - that should be included in the backup. +Click the *Query Options* tab to continue. Use these additional fields to specify +the type of statements that should be included in the backup. - * Move the switch next to *Use Column Inserts* towards right 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* towards right 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 *Use Insert commands* towards right 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. + * Use the *Maximum rows per INSERT command* field to controls the maximum + number of rows per INSERT command. **Note:** This option is visible only for + database server greater than or equal to 12. + + * Move the switch next to *On conflict do nothing to INSERT command* towards + right position to add ON CONFLICT DO NOTHING to INSERT command. + This option is not valid unless *Use INSERT commands*, *Use Column INSERTS* + or *Maximum rows per INSERT command* is also specified. + **Note:** This option is visible only for database server greater than or + equal to 12. * Move the switch next to *Include DROP DATABASE statement* towards right 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 *Include IF EXISTS clause* towards right + position to add an IF EXISTS clause to drop databases and other objects. + This option is not valid unless *Include DROP DATABASE statement* is also set. + + +Click the *Table Options* tab to continue. Use the fields in the *Table Options* +tab related to tables that should be included in the backup. + + * Move the switch next to *Use Column INSERTS* towards right 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 *Load via partition root* towards right 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. + + * Move the switch next to *With OIDs* towards right position to include object + identifiers as part of the table data for each table. + +Click the *Options* tab to continue. Use the fields in the *Options* +tab to provide other backup options. .. image:: images/backup_server_disable.png :alt: Disable option on backup server dialog @@ -106,11 +161,8 @@ tab to provide options related to data or pgAdmin objects that correspond to *pg * Move switches in the **Miscellaneous** field box to specify miscellaneous backup options. - * Move the switch next to *With OIDs* towards right position to include object - identifiers as part of the table data for each table. - * Move the switch next to *Verbose messages* towards left position to instruct - *pg_dump* to exclude verbose messages. + *pg_dumpall* to exclude verbose messages. * Move the switch next to *Force double quotes on identifiers* towards right position to force the quoting of all identifiers. @@ -119,9 +171,21 @@ tab to provide options related to data or pgAdmin objects that correspond to *pg 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. + * Use the *Extra float digits* field to use the specified value when dumping + floating-point data, instead of the maximum available precision. + + * Use the *Lock wait timeout* field to do not wait forever to acquire shared + table locks at the beginning of the dump. Instead, fail if unable to lock a + table within the specified timeout. + +When you’ve specified the details that will be incorporated into the pg_dumpall +command: + +* Click the *Backup* button to build and execute a command that builds a backup + based on your selections on the *Backup Server* dialog. + +* Click the *Cancel* button to exit without saving work. pgAdmin will run the backup process in background. You can view all the background process with there running status and logs on the :ref:`Processes ` -tab \ No newline at end of file +tab diff --git a/docs/en_US/release_notes_7_5.rst b/docs/en_US/release_notes_7_5.rst index 67fccd7cc..7c00e984a 100644 --- a/docs/en_US/release_notes_7_5.rst +++ b/docs/en_US/release_notes_7_5.rst @@ -21,6 +21,8 @@ New features ************ | `Issue #6369 `_ - Added support to detach partitions using concurrently and finalize. + | `Issue #6416 `_ - Added new/missing parameters to pg_dumpall (Backup Server). + | `Issue #6417 `_ - Added new/missing parameters to pg_dump (Backup Objects). Housekeeping ************ @@ -39,7 +41,6 @@ Bug fixes | `Issue #6364 `_ - Fixed Query Tool/ PSQL tool tab title not getting updated on database rename. | `Issue #6501 `_ - Fix the query tool auto-complete issue on the server reconnection. | `Issue #6502 `_ - Fix the query tool restore connection issue. - | `Issue #6508 `_ - Fix the crash issue if the query is running and the server is disconnected. | `Issue #6509 `_ - Fix the reconnecton issue if the PostgreSQL server is restarted from the backend. | `Issue #6514 `_ - Fix the connection and stability issues since v7, possibly related to background schema changes. | `Issue #6515 `_ - Fixed an issue where the query tool is unable to execute a query on Postgres 10 and below versions. diff --git a/web/pgadmin/tools/backup/__init__.py b/web/pgadmin/tools/backup/__init__.py index 09b265eb6..d47fef034 100644 --- a/web/pgadmin/tools/backup/__init__.py +++ b/web/pgadmin/tools/backup/__init__.py @@ -241,8 +241,6 @@ def _get_args_params_values(data, conn, backup_obj_type, backup_file, server, if backup_obj_type == 'globals': args.append('--globals-only') - set_param('verbose', '--verbose') - set_param('dqoute', '--quote-all-identifiers') set_value('role', '--role') if backup_obj_type == 'objects' and data.get('format', None): @@ -253,42 +251,90 @@ def _get_args_params_values(data, conn, backup_obj_type, backup_file, server, 'directory': 'd' }[data['format']])]) - set_param('blobs', '--blobs', data['format'] in ['custom', 'tar']) - set_value('ratio', '--compress', None, - ['custom', 'plain', 'directory']) - - set_param('only_data', '--data-only', - data.get('only_data', None)) - set_param('disable_trigger', '--disable-triggers', - data.get('only_data', None) and - data.get('format', '') == 'plain') - - set_param('only_schema', '--schema-only', - data.get('only_schema', None) and - not data.get('only_data', None)) - - 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') - set_param('dns_privilege', '--no-privileges') - set_param('dns_tablespace', '--no-tablespaces') - set_param('dns_unlogged_tbl_data', '--no-unlogged-table-data') - set_param('use_insert_commands', '--inserts') - set_param('use_column_inserts', '--column-inserts') - set_param('disable_quoting', '--disable-dollar-quoting') - set_param('with_oids', '--oids') - set_param('use_set_session_auth', '--use-set-session-authorization') - - set_param('no_comments', '--no-comments', manager.version >= 110000) - set_param('load_via_partition_root', '--load-via-partition-root', - manager.version >= 110000) + # --blobs is deprecated from v16 + if manager.version >= 160000: + set_param('blobs', 'large-objects', + data['format'] in ['custom', 'tar']) + else: + set_param('blobs', '--blobs', data['format'] in ['custom', 'tar']) + set_value('ratio', '--compress') set_value('encoding', '--encoding') set_value('no_of_jobs', '--jobs') + # Data options + set_param('only_data', '--data-only', + data.get('only_data', None)) + set_param('only_schema', '--schema-only', + data.get('only_schema', None) and + not data.get('only_data', None)) + set_param('only_tablespaces', '--tablespaces-only', + data.get('only_tablespaces', None)) + set_param('only_roles', '--roles-only', + data.get('only_roles', None)) + + # Sections + set_param('pre_data', '--section=pre-data') + set_param('data', '--section=data') + set_param('post_data', '--section=post-data') + + # Do not Save + set_param('dns_owner', '--no-owner') + set_param('dns_privilege', '--no-privileges') + set_param('dns_tablespace', '--no-tablespaces') + set_param('dns_unlogged_tbl_data', '--no-unlogged-table-data') + set_param('dns_comments', '--no-comments', manager.version >= 110000) + set_param('dns_publications', '--no-publications', + manager.version >= 110000) + set_param('dns_subscriptions', '--no-subscriptions', + manager.version >= 110000) + set_param('dns_security_labels', '--no-security-labels', + manager.version >= 110000) + set_param('dns_toast_compression', '--no-toast-compression', + manager.version >= 140000) + set_param('dns_table_access_method', '--no-table-access-method', + manager.version >= 150000) + set_param('dns_no_role_passwords', '--no-role-passwords') + + # Query Options + set_param('use_insert_commands', '--inserts') + set_value('max_rows_per_insert', '--rows-per-insert', None, + manager.version >= 120000) + set_param('on_conflict_do_nothing', '--on-conflict-do-nothing', + manager.version >= 120000) + set_param('include_create_database', '--create') + set_param('include_drop_database', '--clean') + set_param('if_exists', '--if-exists') + + # Table options + set_param('use_column_inserts', '--column-inserts') + set_param('load_via_partition_root', '--load-via-partition-root', + manager.version >= 110000) + set_param('with_oids', '--oids') + set_param('enable_row_security', '--enable-row-security') + set_value('exclude_table_data', '--exclude-table-data') + set_value('table_and_children', '--table-and-children', None, + manager.version >= 160000) + set_value('exclude_table_and_children', '--exclude-table-and-children', + None, manager.version >= 160000) + set_value('exclude_table_data_and_children', + '--exclude-table-data-and-children', None, + manager.version >= 160000) + + # Disable options + set_param('disable_trigger', '--disable-triggers', + data.get('only_data', None) and + data.get('format', '') == 'plain') + set_param('disable_quoting', '--disable-dollar-quoting') + + # Misc Options + set_param('verbose', '--verbose') + set_param('dqoute', '--quote-all-identifiers') + set_param('use_set_session_auth', '--use-set-session-authorization') + set_value('extra_float_digits', '--extra-float-digits', None, + manager.version >= 120000) + set_value('lock_wait_timeout', '--lock-wait-timeout') + args.extend( functools.reduce(operator.iconcat, map( lambda s: ['--schema', r'{0}'.format(driver.qtIdent(conn, s). diff --git a/web/pgadmin/tools/backup/static/js/backup.js b/web/pgadmin/tools/backup/static/js/backup.js index d1b60434d..aff92ac08 100644 --- a/web/pgadmin/tools/backup/static/js/backup.js +++ b/web/pgadmin/tools/backup/static/js/backup.js @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////// import {getUtilityView, removeNodeView} from '../../../../browser/static/js/utility_view'; import { getNodeListByName, getNodeAjaxOptions } from '../../../../browser/static/js/node_ajax'; -import BackupSchema, {getSectionSchema, getTypeObjSchema, getSaveOptSchema, getQueryOptionSchema, getDisabledOptionSchema, getMiscellaneousSchema} from './backup.ui'; +import BackupSchema, {getSectionSchema, getTypeObjSchema, getSaveOptSchema, getDisabledOptionSchema, getMiscellaneousSchema} from './backup.ui'; import BackupGlobalSchema, {getMiscellaneousSchema as getMiscellaneousGlobalSchema} from './backupGlobal.ui'; import Notify from '../../../../static/js/helpers/Notifier'; import getApiInstance from 'sources/api_instance'; @@ -254,9 +254,8 @@ define([ let itemNodeData = pgBrowser.tree.findNodeByDomElement(selectedNode).getData(); return new BackupSchema( ()=> getSectionSchema(), - ()=> getTypeObjSchema({backupType: backupType}), + ()=> getTypeObjSchema(), ()=> getSaveOptSchema({nodeInfo: treeNodeInfo}), - ()=> getQueryOptionSchema({nodeInfo: treeNodeInfo, backupType: backupType}), ()=> getDisabledOptionSchema({nodeInfo: treeNodeInfo}), ()=> getMiscellaneousSchema({nodeInfo: treeNodeInfo}), { diff --git a/web/pgadmin/tools/backup/static/js/backup.ui.js b/web/pgadmin/tools/backup/static/js/backup.ui.js index e787d30ba..7060b7108 100644 --- a/web/pgadmin/tools/backup/static/js/backup.ui.js +++ b/web/pgadmin/tools/backup/static/js/backup.ui.js @@ -33,30 +33,36 @@ export class SectionSchema extends BaseUISchema { label: gettext('Pre-data'), type: 'switch', group: gettext('Sections'), - deps: ['only_data', 'only_schema'], + deps: ['only_data', 'only_schema', 'only_tablespaces', 'only_roles'], disabled: function(state) { return state.only_data || - state.only_schema; + state.only_schema || + state.only_tablespaces || + state.only_roles; }, }, { id: 'data', label: gettext('Data'), type: 'switch', group: gettext('Sections'), - deps: ['only_data', 'only_schema'], + deps: ['only_data', 'only_schema', 'only_tablespaces', 'only_roles'], disabled: function(state) { return state.only_data || - state.only_schema; + state.only_schema || + state.only_tablespaces || + state.only_roles; }, }, { id: 'post_data', label: gettext('Post-data'), type: 'switch', group: gettext('Sections'), - deps: ['only_data', 'only_schema'], + deps: ['only_data', 'only_schema', 'only_tablespaces', 'only_roles'], disabled: function(state) { return state.only_data || - state.only_schema; + state.only_schema || + state.only_tablespaces || + state.only_roles; }, } ]; @@ -72,11 +78,8 @@ export class TypeObjSchema extends BaseUISchema { super(); this.fieldOptions = { - backupType: null, ...fieldOptions, }; - - this.backupType = this.fieldOptions.backupType; } get idAttribute() { @@ -91,32 +94,70 @@ export class TypeObjSchema extends BaseUISchema { label: gettext('Only data'), type: 'switch', group: gettext('Type of objects'), - deps: ['pre_data', 'data', 'post_data', 'only_schema'], + deps: ['pre_data', 'data', 'post_data', 'only_schema', + 'only_tablespaces', 'only_roles'], disabled: function(state) { return state.pre_data || state.data || state.post_data || - state.only_schema; + state.only_schema || + state.only_tablespaces || + state.only_roles; }, }, { id: 'only_schema', - label: gettext('Only schema'), + label: gettext('Only schemas'), type: 'switch', group: gettext('Type of objects'), - deps: ['pre_data', 'data', 'post_data', 'only_data'], + deps: ['pre_data', 'data', 'post_data', 'only_data', + 'only_tablespaces', 'only_roles'], disabled: function(state) { return state.pre_data || state.data || state.post_data || - state.only_data; + state.only_data || + state.only_tablespaces || + state.only_roles; }, + }, { + id: 'only_tablespaces', + label: gettext('Only tablespaces'), + type: 'switch', + group: gettext('Type of objects'), + deps: ['pre_data', 'data', 'post_data', 'only_data', 'only_schema', + 'only_roles'], + disabled: function(state) { + return state.pre_data || + state.data || + state.post_data || + state.only_data || + state.only_schema || + state.only_roles; + }, + visible: isVisibleForObjectBackup(obj?._top?.backupType) + }, { + id: 'only_roles', + label: gettext('Only roles'), + type: 'switch', + group: gettext('Type of objects'), + deps: ['pre_data', 'data', 'post_data', 'only_data', 'only_schema', + 'only_tablespaces'], + disabled: function(state) { + return state.pre_data || + state.data || + state.post_data || + state.only_data || + state.only_schema || + state.only_tablespaces; + }, + visible: isVisibleForObjectBackup(obj?._top?.backupType) }, { id: 'blobs', label: gettext('Blobs'), type: 'switch', group: gettext('Type of objects'), visible: function(state) { - if (!_.isUndefined(obj.backupType) && obj.backupType === 'server') { + if (!isVisibleForServerBackup(obj?._top?.backupType)) { state.blobs = false; return false; } @@ -147,23 +188,30 @@ export class SaveOptSchema extends BaseUISchema { return 'id'; } - get baseFields() { + let obj = this; return [{ id: 'dns_owner', label: gettext('Owner'), type: 'switch', disabled: false, group: gettext('Do not save'), + }, { + id: 'dns_no_role_passwords', + label: gettext('Role passwords'), + type: 'switch', + disabled: false, + group: gettext('Do not save'), + visible: isVisibleForObjectBackup(obj?._top?.backupType), }, { id: 'dns_privilege', - label: gettext('Privilege'), + label: gettext('Privileges'), type: 'switch', disabled: false, group: gettext('Do not save'), }, { id: 'dns_tablespace', - label: gettext('Tablespace'), + label: gettext('Tablespaces'), type: 'switch', disabled: false, group: gettext('Do not save'), @@ -174,12 +222,47 @@ export class SaveOptSchema extends BaseUISchema { disabled: false, group: gettext('Do not save'), }, { - id: 'no_comments', + id: 'dns_comments', label: gettext('Comments'), type: 'switch', disabled: false, group: gettext('Do not save'), min_version: 110000 + }, { + id: 'dns_publications', + label: gettext('Publications'), + type: 'switch', + disabled: false, + group: gettext('Do not save'), + min_version: 110000 + }, { + id: 'dns_subscriptions', + label: gettext('Subscriptions'), + type: 'switch', + disabled: false, + group: gettext('Do not save'), + min_version: 110000 + }, { + id: 'dns_security_labels', + label: gettext('Security labels'), + type: 'switch', + disabled: false, + group: gettext('Do not save'), + min_version: 110000 + }, { + id: 'dns_toast_compression', + label: gettext('Toast compressions'), + type: 'switch', + disabled: false, + group: gettext('Do not save'), + min_version: 140000 + }, { + id: 'dns_table_access_method', + label: gettext('Table access methods'), + type: 'switch', + disabled: false, + group: gettext('Do not save'), + min_version: 150000 }]; } } @@ -188,77 +271,12 @@ export function getSaveOptSchema(fieldOptions) { return new SaveOptSchema(fieldOptions); } -function isVisible () { - return !(!_.isUndefined(this.backupType) && this.backupType === 'server'); +function isVisibleForServerBackup(backupType) { + return !(!_.isUndefined(backupType) && backupType === 'server'); } -export class QueryOptionSchema extends BaseUISchema { - constructor(fieldOptions={}, initValues={}) { - super({ - id: null, - ...initValues, - }); - - this.fieldOptions = { - nodeInfo: null, - backupType: null, - ...fieldOptions, - }; - this.backupType = fieldOptions.backupType; - } - - get idAttribute() { - return 'id'; - } - - - get baseFields() { - return [{ - id: 'use_column_inserts', - label: gettext('Use Column Inserts'), - type: 'switch', - disabled: false, - group: gettext('Queries'), - }, { - id: 'use_insert_commands', - label: gettext('Use Insert Commands'), - type: 'switch', - disabled: false, - group: gettext('Queries'), - }, { - id: 'include_create_database', - label: gettext('Include CREATE DATABASE statement'), - type: 'switch', - disabled: false, - group: gettext('Queries'), - visible: isVisible, - }, { - id: 'include_drop_database', - label: gettext('Include DROP DATABASE statement'), - type: 'switch', - group: gettext('Queries'), - deps: ['only_data'], - disabled: function(state) { - if (state.only_data) { - state.include_drop_database = false; - return true; - } - return false; - }, - }, { - id: 'load_via_partition_root', - label: gettext('Load Via Partition Root'), - type: 'switch', - disabled: false, - group: gettext('Queries'), - min_version: 110000, - visible: isVisible, - }]; - } -} - -export function getQueryOptionSchema(fieldOptions) { - return new QueryOptionSchema(fieldOptions); +function isVisibleForObjectBackup(backupType) { + return !(!_.isUndefined(backupType) && backupType === 'backup_objects'); } export class DisabledOptionSchema extends BaseUISchema { @@ -282,7 +300,7 @@ export class DisabledOptionSchema extends BaseUISchema { get baseFields() { return [{ id: 'disable_trigger', - label: gettext('Trigger'), + label: gettext('Triggers'), type: 'switch', group: gettext('Disable'), deps: ['only_data'], @@ -323,26 +341,7 @@ export class MiscellaneousSchema extends BaseUISchema { get baseFields() { - let obj = this; return [{ - id: 'with_oids', - label: gettext('With OID(s)'), - type: 'switch', - deps: ['use_column_inserts', 'use_insert_commands'], - group: gettext('Miscellaneous'), - disabled: function(state) { - let serverInfo = _.isUndefined(obj.fieldOptions.nodeInfo) ? undefined : obj.fieldOptions.nodeInfo.server; - - if (!_.isUndefined(serverInfo) && serverInfo.version >= 120000) - return true; - - if (state.use_column_inserts || state.use_insert_commands) { - state.with_oids = false; - return true; - } - return false; - }, - }, { id: 'verbose', label: gettext('Verbose messages'), type: 'switch', @@ -360,6 +359,19 @@ export class MiscellaneousSchema extends BaseUISchema { type: 'switch', disabled: false, group: gettext('Miscellaneous'), + }, { + id: 'extra_float_digits', + label: gettext('Extra float digits'), + type: 'int', + disabled: false, + group: gettext('Miscellaneous'), + min_version: 120000 + }, { + id: 'lock_wait_timeout', + label: gettext('Lock wait timeout'), + type: 'int', + disabled: false, + group: gettext('Miscellaneous') }]; } } @@ -369,7 +381,7 @@ export function getMiscellaneousSchema(fieldOptions) { } export default class BackupSchema extends BaseUISchema { - constructor(sectionSchema, typeObjSchema, saveOptSchema, queryOptionSchema, disabledOptionSchema, miscellaneousSchema, fieldOptions = {}, treeNodeInfo=[], pgBrowser=null, backupType='server') { + constructor(sectionSchema, typeObjSchema, saveOptSchema, disabledOptionSchema, miscellaneousSchema, fieldOptions = {}, treeNodeInfo=[], pgBrowser=null, backupType='server') { super({ file: undefined, format: 'custom', @@ -390,7 +402,6 @@ export default class BackupSchema extends BaseUISchema { this.getSectionSchema = sectionSchema; this.getTypeObjSchema = typeObjSchema; this.getSaveOptSchema = saveOptSchema; - this.getQueryOptionSchema = queryOptionSchema; this.getDisabledOptionSchema = disabledOptionSchema; this.getMiscellaneousSchema = miscellaneousSchema; } @@ -437,7 +448,7 @@ export default class BackupSchema extends BaseUISchema { }, ], visible: function(state) { - if (!_.isUndefined(obj.backupType) && obj.backupType === 'server') { + if (!isVisibleForServerBackup(obj.backupType)) { state.format = 'plain'; return false; } @@ -453,7 +464,7 @@ export default class BackupSchema extends BaseUISchema { disabled: function(state) { return (state.format === 'tar'); }, - visible: isVisible, + visible: isVisibleForServerBackup(obj.backupType), }, { id: 'encoding', label: gettext('Encoding'), @@ -461,7 +472,7 @@ export default class BackupSchema extends BaseUISchema { disabled: false, options: obj.fieldOptions.encoding, min_version: 110000, - visible: isVisible + visible: isVisibleForServerBackup(obj.backupType) }, { id: 'no_of_jobs', label: gettext('Number of jobs'), @@ -470,7 +481,7 @@ export default class BackupSchema extends BaseUISchema { disabled: function(state) { return (state.format !== 'directory'); }, - visible: isVisible, + visible: isVisibleForServerBackup(obj.backupType), }, { id: 'role', label: gettext('Role name'), @@ -490,24 +501,155 @@ export default class BackupSchema extends BaseUISchema { }, { type: 'nested-fieldset', label: gettext('Sections'), - group: gettext('Data/Objects'), + group: gettext('Data Options'), schema:new getSectionSchema(), - visible: isVisible, + visible: isVisibleForServerBackup(obj.backupType) }, { type: 'nested-fieldset', label: gettext('Type of objects'), - group: gettext('Data/Objects'), + group: gettext('Data Options'), schema: obj.getTypeObjSchema() }, { type: 'nested-fieldset', label: gettext('Do not save'), - group: gettext('Data/Objects'), + group: gettext('Data Options'), schema: obj.getSaveOptSchema(), }, { - type: 'nested-fieldset', - label: gettext('Queries'), - group: gettext('Options'), - schema: obj.getQueryOptionSchema(), + id: 'use_insert_commands', + label: gettext('Use INSERT Commands'), + type: 'switch', + disabled: false, + group: gettext('Query Options'), + }, { + id: 'max_rows_per_insert', + label: gettext('Maximum rows per INSERT command'), + type: 'int', min: 1, + disabled: false, + group: gettext('Query Options'), + min_version: 120000 + }, { + id: 'on_conflict_do_nothing', + label: gettext('On conflict do nothing to INSERT command'), + type: 'switch', + group: gettext('Query Options'), + min_version: 120000, + deps: ['use_insert_commands', 'rows_per_insert', 'use_column_inserts'], + disabled: function(state) { + if (state.use_insert_commands || state.use_column_inserts || state.rows_per_insert > 0) { + return false; + } + state.on_conflict_do_nothing = false; + return true; + }, + }, { + id: 'include_create_database', + label: gettext('Include CREATE DATABASE statement'), + type: 'switch', + disabled: false, + group: gettext('Query Options'), + visible: isVisibleForServerBackup(obj.backupType), + }, { + id: 'include_drop_database', + label: gettext('Include DROP DATABASE statement'), + type: 'switch', + group: gettext('Query Options'), + deps: ['only_data'], + disabled: function(state) { + if (state.only_data) { + state.include_drop_database = false; + return true; + } + return false; + }, + }, { + id: 'if_exists', + label: gettext('Include IF EXISTS clause'), + type: 'switch', + group: gettext('Query Options'), + deps: ['only_data, include_drop_database'], + disabled: function(state) { + if (state.include_drop_database) { + return false; + } + state.if_exists = false; + return true; + }, + }, { + id: 'use_column_inserts', + label: gettext('Use Column INSERTS'), + type: 'switch', + disabled: false, + group: gettext('Table Options'), + }, { + id: 'load_via_partition_root', + label: gettext('Load via partition root'), + type: 'switch', + disabled: false, + group: gettext('Table Options'), + min_version: 110000 + }, { + id: 'enable_row_security', + label: gettext('Enable row security'), + type: 'switch', + group: gettext('Table Options'), + deps:['use_insert_commands'], + disabled: function(state) { + if (state.use_insert_commands) { + return false; + } + state.enable_row_security = false; + return true; + }, + visible: isVisibleForServerBackup(obj.backupType) + }, { + id: 'with_oids', + label: gettext('With OID(s)'), + type: 'switch', + deps: ['use_column_inserts', 'use_insert_commands'], + group: gettext('Table Options'), + disabled: function(state) { + let serverInfo = _.isUndefined(obj.fieldOptions.nodeInfo) ? undefined : obj.fieldOptions.nodeInfo.server; + + if (!_.isUndefined(serverInfo) && serverInfo.version >= 120000) + return true; + + if (state.use_column_inserts || state.use_insert_commands) { + state.with_oids = false; + return true; + } + return false; + }, + }, { + id: 'exclude_table_data', + label: gettext('Exclude table data'), + type: 'text', + disabled: false, + group: gettext('Table Options'), + visible: isVisibleForServerBackup(obj.backupType) + }, { + id: 'table_and_children', + label: gettext('Table and Children'), + type: 'text', + disabled: false, + group: gettext('Table Options'), + min_version: 160000, + visible: isVisibleForServerBackup(obj.backupType) + }, { + id: 'exclude_table_and_children', + label: gettext('Exclude table and children'), + type: 'text', + disabled: false, + group: gettext('Table Options'), + min_version: 160000, + visible: isVisibleForServerBackup(obj.backupType) + }, { + id: 'exclude_table_data_and_children', + label: gettext('Exclude table data and children'), + type: 'text', + disabled: false, + group: gettext('Table Options'), + min_version: 160000, + visible: isVisibleForServerBackup(obj.backupType) }, { type: 'nested-fieldset', label: gettext('Disable'), @@ -534,5 +676,4 @@ export default class BackupSchema extends BaseUISchema { } } } - } diff --git a/web/pgadmin/tools/backup/tests/test_backup_create_job_unit_test.py b/web/pgadmin/tools/backup/tests/test_backup_create_job_unit_test.py index 3e4eb03d9..1b2f849e5 100644 --- a/web/pgadmin/tools/backup/tests/test_backup_create_job_unit_test.py +++ b/web/pgadmin/tools/backup/tests/test_backup_create_job_unit_test.py @@ -18,6 +18,15 @@ from pgadmin.browser.server_groups.servers.databases.tests import utils as \ from unittest.mock import patch, MagicMock from config import PG_DEFAULT_DRIVER +BACKUP_OBJECT_URL = '/backup/job/{0}/object' +BACKUP_SERVER_URL = '/backup/job/{0}' +VERBOSE = '--verbose' +FORMAT_C = '--format=c' +FORMAT_P = '--format=p' +BLOBS = '--blobs' +DATA_ONLY = '--data-only' +SCHEMA_ONLY = '--schema-only' + class BackupCreateJobTest(BaseTestGenerator): """Test the BackupCreateJob class""" @@ -42,8 +51,8 @@ class BackupCreateJobTest(BaseTestGenerator): tables=[], database='postgres' ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', '--format=c', '--blobs'], + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, FORMAT_C, BLOBS], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), @@ -67,8 +76,8 @@ class BackupCreateJobTest(BaseTestGenerator): tables=[], database='postgres' ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', '--format=d'], + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, '--format=d'], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), @@ -94,8 +103,8 @@ class BackupCreateJobTest(BaseTestGenerator): pre_data=True, post_data=True ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', '--format=c', + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, FORMAT_C, '--section=pre-data', '--section=data', '--section=post-data'], not_expected_cmd_opts=[], @@ -122,8 +131,8 @@ class BackupCreateJobTest(BaseTestGenerator): only_data=True, only_schema=False ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', '--format=p', '--data-only'], + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, FORMAT_P, DATA_ONLY], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), @@ -149,9 +158,9 @@ class BackupCreateJobTest(BaseTestGenerator): only_schema=True, dns_owner=True ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', '--format=p', '--data-only'], - not_expected_cmd_opts=['--schema-only'], + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, FORMAT_P, DATA_ONLY], + not_expected_cmd_opts=[SCHEMA_ONLY], expected_exit_code=[0, None] )), ('When backup the object with option only_schema', @@ -175,8 +184,8 @@ class BackupCreateJobTest(BaseTestGenerator): only_data=False, only_schema=True ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', '--format=p', '--schema-only'], + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, FORMAT_P, SCHEMA_ONLY], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), @@ -200,8 +209,8 @@ class BackupCreateJobTest(BaseTestGenerator): database='postgres', dns_owner=True ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', '--format=p', '--no-owner'], + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, FORMAT_P, '--no-owner'], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), @@ -228,14 +237,15 @@ class BackupCreateJobTest(BaseTestGenerator): dns_unlogged_tbl_data=True, dns_tablespace=True ), - url='/backup/job/{0}/object', + url=BACKUP_OBJECT_URL, expected_cmd_opts=['--no-privileges', '--no-tablespaces', '--no-unlogged-table-data'], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), - ('When backup the object with option - Do not save comments,', + ('When backup the object with option - Do not save Comments,' + 'Publications, Subscriptions, Security Labels', dict( class_params=dict( sid=1, @@ -253,15 +263,77 @@ class BackupCreateJobTest(BaseTestGenerator): schemas=[], tables=[], database='postgres', - no_comments=True, + dns_comments=True, + dns_publications=True, + dns_subscriptions=True, + dns_security_labels=True, ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--no-comments'], + url=BACKUP_OBJECT_URL, + expected_cmd_opts=['--no-comments', '--no-publications', + '--no-subscriptions', '--no-security-labels'], not_expected_cmd_opts=[], expected_exit_code=[0, None], server_min_version=110000, - message='Backup object with --no-comments is not supported ' - 'by EPAS/PG server less than 11.0' + message='Backup object with --no-comments, --no-publications,' + '--no-subscriptions, --no-security-labels is not ' + 'supported by EPAS/PG server less than 11.0' + )), + ('When backup the object with option - Do not save Toast Compression', + 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', + dns_toast_compression=True, + ), + url=BACKUP_OBJECT_URL, + expected_cmd_opts=['--no-toast-compression'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None], + server_min_version=140000, + message='Backup object with --no-toast-compression is not' + 'supported by EPAS/PG server less than 14.0' + )), + ('When backup the object with option - Do not save Table Access ' + 'Method,', + 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', + dns_table_access_method=True, + ), + url=BACKUP_OBJECT_URL, + expected_cmd_opts=['--no-table-access-method'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None], + server_min_version=150000, + message='Backup object with --no-table-access-method is not ' + 'supported by EPAS/PG server less than 15.0' )), ('When backup the object with option - all queries', dict( @@ -284,14 +356,47 @@ class BackupCreateJobTest(BaseTestGenerator): use_column_inserts=True, include_create_database=True, use_insert_commands=True, - include_drop_database=True + include_drop_database=True, + if_exists=True ), - url='/backup/job/{0}/object', + url=BACKUP_OBJECT_URL, expected_cmd_opts=['--create', '--clean', '--inserts', - '--column-inserts'], + '--column-inserts', '--if-exists'], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), + ('When backup the object with option - Rows per insert and ' + 'On conflict do nothing', + 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', + max_rows_per_insert="200", + on_conflict_do_nothing=True + ), + url=BACKUP_OBJECT_URL, + expected_cmd_opts=['--rows-per-insert', '200', + '--on-conflict-do-nothing'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None], + server_min_version=120000, + message='Backup object with --rows-per-insert and ' + '--on-conflict-do-nothing are not supported by EPAS/PG ' + 'server less than 12.0' + )), ('When backup the object with option - load via partition root', dict( class_params=dict( @@ -312,7 +417,7 @@ class BackupCreateJobTest(BaseTestGenerator): database='postgres', load_via_partition_root=True, ), - url='/backup/job/{0}/object', + url=BACKUP_OBJECT_URL, expected_cmd_opts=['--load-via-partition-root'], not_expected_cmd_opts=[], expected_exit_code=[0, None], @@ -320,6 +425,59 @@ class BackupCreateJobTest(BaseTestGenerator): 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 - enable row security', + 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', + enable_row_security=True, + ), + url=BACKUP_OBJECT_URL, + expected_cmd_opts=['--enable-row-security'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None] + )), + ('When backup the object with option - exclude 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_file', + format='plain', + verbose=True, + schemas=[], + tables=[], + database='postgres', + exclude_table_data='table1', + ), + url=BACKUP_OBJECT_URL, + expected_cmd_opts=['--exclude-table-data', 'table1'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None], + server_min_version=110000, + message='Backup object with --exclude-table-data 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( @@ -341,11 +499,12 @@ class BackupCreateJobTest(BaseTestGenerator): use_column_inserts=True, include_create_database=True, use_insert_commands=True, - include_drop_database=True + include_drop_database=True, + if_exists=True ), - url='/backup/job/{0}/object', + url=BACKUP_OBJECT_URL, expected_cmd_opts=['--inserts', '--clean', - '--column-inserts', '--create'], + '--column-inserts', '--create', '--if-exists'], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), @@ -372,13 +531,66 @@ class BackupCreateJobTest(BaseTestGenerator): with_oids=True, dqoute=True ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', '--quote-all-identifiers', + url=BACKUP_OBJECT_URL, + 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 object with option - Extra float digits', + 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', + extra_float_digits="5" + ), + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, '--extra-float-digits', '5'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None], + server_min_version=120000, + message='Backup object with --extra-float-digits are not ' + 'supported by EPAS/PG server less than 12.0' + )), + ('When backup the object with option - Lock wait timeout', + 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', + lock_wait_timeout="1000" + ), + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, '--lock-wait-timeout', '1000'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None] + )), ('When backup the object with format tar', dict( class_params=dict( @@ -399,9 +611,9 @@ class BackupCreateJobTest(BaseTestGenerator): database='postgres', blobs=True, ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', - '--blobs', + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, + BLOBS, '--format=t'], not_expected_cmd_opts=[], expected_exit_code=[0, None] @@ -426,8 +638,8 @@ class BackupCreateJobTest(BaseTestGenerator): tables=[], database='postgres' ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', '--format=c', '--blobs', + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, FORMAT_C, BLOBS, '--schema', 'schema1'], not_expected_cmd_opts=[], expected_exit_code=[0, None] @@ -452,8 +664,8 @@ class BackupCreateJobTest(BaseTestGenerator): tables=[['public', 'table1']], database='postgres' ), - url='/backup/job/{0}/object', - expected_cmd_opts=['--verbose', '--format=c', '--blobs', + url=BACKUP_OBJECT_URL, + expected_cmd_opts=[VERBOSE, FORMAT_C, BLOBS, '--table', 'public.table1'], not_expected_cmd_opts=[], expected_exit_code=[0, None] @@ -475,8 +687,8 @@ class BackupCreateJobTest(BaseTestGenerator): verbose=True, type='server' ), - url='/backup/job/{0}', - expected_cmd_opts=['--verbose'], + url=BACKUP_SERVER_URL, + expected_cmd_opts=[VERBOSE], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), @@ -498,8 +710,8 @@ class BackupCreateJobTest(BaseTestGenerator): only_data=True, only_schema=False ), - url='/backup/job/{0}', - expected_cmd_opts=['--verbose', '--data-only'], + url=BACKUP_SERVER_URL, + expected_cmd_opts=[VERBOSE, DATA_ONLY], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), @@ -522,8 +734,54 @@ class BackupCreateJobTest(BaseTestGenerator): only_data=False, only_schema=True ), - url='/backup/job/{0}', - expected_cmd_opts=['--verbose', '--schema-only'], + url=BACKUP_SERVER_URL, + expected_cmd_opts=[VERBOSE, SCHEMA_ONLY], + not_expected_cmd_opts=[], + expected_exit_code=[0, None] + )), + ('When backup the server with option only_tablespaces', + 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_tablespaces=True + ), + url=BACKUP_SERVER_URL, + expected_cmd_opts=[VERBOSE, '--tablespaces-only'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None] + )), + ('When backup the server with option only_roles', + 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_roles=True + ), + url=BACKUP_SERVER_URL, + expected_cmd_opts=[VERBOSE, '--roles-only'], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), @@ -548,14 +806,15 @@ class BackupCreateJobTest(BaseTestGenerator): dns_unlogged_tbl_data=True, dns_tablespace=True ), - url='/backup/job/{0}', + url=BACKUP_SERVER_URL, 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,', + ('When backup the server with option - Do not save Comments, ' + 'Publications, Subscriptions, Security Labels', dict( class_params=dict( sid=1, @@ -571,15 +830,96 @@ class BackupCreateJobTest(BaseTestGenerator): type='server', format='plain', verbose=True, - no_comments=True, + dns_comments=True, + dns_publications=True, + dns_subscriptions=True, + dns_security_labels=True, ), - url='/backup/job/{0}', - expected_cmd_opts=['--no-comments'], + url=BACKUP_SERVER_URL, + expected_cmd_opts=['--no-comments', '--no-publications', + '--no-subscriptions', '--no-security-labels'], not_expected_cmd_opts=[], expected_exit_code=[0, None], server_min_version=110000, - message='Backup server with --no-comments is not supported ' - 'by EPAS/PG server less than 11.0' + message='Backup server with --no-comments, --no-publications,' + '--no-subscriptions, --no-security-labels is not ' + 'supported by EPAS/PG server less than 11.0' + )), + ('When backup the server with option - Do not save Toast Compression', + 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_toast_compression=True, + ), + url=BACKUP_SERVER_URL, + expected_cmd_opts=['--no-toast-compression'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None], + server_min_version=140000, + message='Backup server with --no-toast-compression is not' + 'supported by EPAS/PG server less than 14.0' + )), + ('When backup the server with option - Do not save Table Access ' + 'Method,', + 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_table_access_method=True, + ), + url=BACKUP_SERVER_URL, + expected_cmd_opts=['--no-table-access-method'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None], + server_min_version=150000, + message='Backup server with --no-table-access-method is not ' + 'supported by EPAS/PG server less than 15.0' + )), + ('When backup the server with option - Do not save Role passwords ', + 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_no_role_passwords=True, + ), + url=BACKUP_SERVER_URL, + expected_cmd_opts=['--no-role-passwords'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None] )), ('When backup the server with option - all queries', dict( @@ -599,14 +939,45 @@ class BackupCreateJobTest(BaseTestGenerator): verbose=True, use_column_inserts=True, use_insert_commands=True, - include_drop_database=True + include_drop_database=True, + if_exists=True ), - url='/backup/job/{0}', + url=BACKUP_SERVER_URL, expected_cmd_opts=['--clean', '--inserts', - '--column-inserts'], + '--column-inserts', '--if-exists'], not_expected_cmd_opts=[], expected_exit_code=[0, None] )), + ('When backup the server with option - Rows per insert and ' + 'On conflict do nothing', + 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, + max_rows_per_insert="200", + on_conflict_do_nothing=True + ), + url=BACKUP_SERVER_URL, + expected_cmd_opts=['--rows-per-insert', '200', + '--on-conflict-do-nothing'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None], + server_min_version=120000, + message='Backup object with --rows-per-insert and ' + '--on-conflict-do-nothing are not supported by EPAS/PG ' + 'server less than 12.0' + )), ('When backup the server with option - miscellaneous', dict( class_params=dict( @@ -627,13 +998,60 @@ class BackupCreateJobTest(BaseTestGenerator): with_oids=True, dqoute=True ), - url='/backup/job/{0}', - expected_cmd_opts=['--verbose', '--quote-all-identifiers', + url=BACKUP_SERVER_URL, + 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 option - Extra float digits', + 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, + extra_float_digits="5" + ), + url=BACKUP_SERVER_URL, + expected_cmd_opts=[VERBOSE, '--extra-float-digits', '5'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None], + server_min_version=120000, + message='Backup server with --extra-float-digits are not ' + 'supported by EPAS/PG server less than 12.0' + )), + ('When backup the server with option - Lock wait timeout', + 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, + lock_wait_timeout="1000" + ), + url=BACKUP_SERVER_URL, + expected_cmd_opts=[VERBOSE, '--lock-wait-timeout', '1000'], + not_expected_cmd_opts=[], + expected_exit_code=[0, None] + )), ('When backup the server with encoding', dict( class_params=dict( @@ -652,7 +1070,7 @@ class BackupCreateJobTest(BaseTestGenerator): type='server', encoding='UTF-8' ), - url='/backup/job/{0}', + url=BACKUP_SERVER_URL, expected_cmd_opts=['--encoding'], not_expected_cmd_opts=[], expected_exit_code=[0, None], @@ -677,7 +1095,7 @@ class BackupCreateJobTest(BaseTestGenerator): verbose=True, type='globals' ), - url='/backup/job/{0}', + url=BACKUP_SERVER_URL, expected_cmd_opts=['--globals-only'], not_expected_cmd_opts=[], expected_exit_code=[0, None] @@ -702,9 +1120,9 @@ class BackupCreateJobTest(BaseTestGenerator): if os.name == 'nt': binary_path = binary_path + '.exe' - retVal = does_utility_exist(binary_path) - if retVal is not None: - self.skipTest(retVal) + ret_val = does_utility_exist(binary_path) + if ret_val is not None: + self.skipTest(ret_val) @patch('pgadmin.tools.backup.Server') @patch('pgadmin.tools.backup.BackupMessage') diff --git a/web/pgadmin/tools/sqleditor/command.py b/web/pgadmin/tools/sqleditor/command.py index 91da4a830..2b824caca 100644 --- a/web/pgadmin/tools/sqleditor/command.py +++ b/web/pgadmin/tools/sqleditor/command.py @@ -693,7 +693,6 @@ class TableCommand(GridCommand): def get_columns_types(self, conn): columns_info = conn.get_column_info() has_oids = self.has_oids() - # table_oid = self.obj_id table_name = None table_nspname = None table_oid = _check_single_table(columns_info)