Skip to content

Commit

Permalink
Add support for restoring plain SQL database dumps. #5871
Browse files Browse the repository at this point in the history
  • Loading branch information
adityatoshniwal committed Feb 24, 2025
1 parent 53077b6 commit 73a55e0
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 49 deletions.
11 changes: 3 additions & 8 deletions web/pgadmin/static/js/SchemaView/FormView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
} from './hooks';
import { registerView, View } from './registry';
import { createFieldControls, listenDepChanges } from './utils';
import FormViewTab from './FormViewTab';

const ErrorMessageBox = () => {
const [key, setKey] = useState(0);
Expand Down Expand Up @@ -181,14 +182,8 @@ export default function FormView({
action={(ref) => ref?.updateIndicator()}
>{
finalGroups.map((tabGroup, idx) =>
<Tab
key={tabGroup.id}
label={tabGroup.label}
data-test={tabGroup.id}
className={
tabGroup.hasError &&
tabValue != idx ? 'tab-with-error' : ''
}
<FormViewTab
key={tabGroup.id} tabGroup={tabGroup} idx={idx} tabValue={tabValue}
/>
)
}{hasSQLTab &&
Expand Down
45 changes: 45 additions & 0 deletions web/pgadmin/static/js/SchemaView/FormViewTab.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2025, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////

import { Tab } from '@mui/material';
import React, { useContext, useState } from 'react';
import { useFieldOptions, useSchemaStateSubscriber } from './hooks';
import { SchemaStateContext } from './SchemaState';
import PropTypes from 'prop-types';

export default function FormViewTab({tabGroup, idx, tabValue, ...props}) {
const accessPath = [tabGroup.id];
const [, setRefreshKey] = useState(0);
const subscriberManager = useSchemaStateSubscriber(setRefreshKey);
const schemaState = useContext(SchemaStateContext);
const options = useFieldOptions(accessPath, schemaState, subscriberManager);

return (
<Tab
key={tabGroup.id}
label={tabGroup.label}
data-test={tabGroup.id}
iconPosition='start'
disabled={options.disabled}
className={
tabGroup.hasError &&
tabValue != idx ? 'tab-with-error' : ''
}
{...props}
/>
);
};

FormViewTab.muiName = Tab.muiName;

FormViewTab.propTypes = {
tabGroup: PropTypes.object,
idx: PropTypes.number,
tabValue: PropTypes.number,
};
8 changes: 6 additions & 2 deletions web/pgadmin/static/js/Theme/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -788,13 +788,17 @@ function getFinalTheme(baseTheme) {
MuiTab: {
styleOverrides: {
root: {
'&.MuiTab-textColorPrimary':{
'&:not(.Mui-disabled).MuiTab-textColorPrimary':{
color: baseTheme.palette.text.primary,
},
'&.Mui-selected': {
color: baseTheme.otherVars.activeColor,
},
}
},
icon: {
fontSize: '1rem',
marginRight: '2px',
},
}
},
MuiBackdrop: {
Expand Down
78 changes: 64 additions & 14 deletions web/pgadmin/tools/restore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,18 @@ def _get_create_req_data():
data = json.loads(request.data)

try:
_file = filename_with_file_manager_path(data['file'])
filepath = filename_with_file_manager_path(data['file'])
except Exception as e:
return True, internal_server_error(errormsg=str(e)), data, None

if _file is None:
if filepath is None:
return True, make_json_response(
status=410,
success=0,
errormsg=_("File could not be found.")
), data, _file
), data, filepath

return False, '', data, _file
return False, '', data, filepath


def _connect_server(sid):
Expand Down Expand Up @@ -263,15 +263,15 @@ def set_multiple(key, param, data, args, driver, conn, with_schema=True):
return False


def _set_args_param_values(data, manager, server, driver, conn, _file):
def get_restore_util_args(data, manager, server, driver, conn, filepath):
"""
add args to the list.
:param data: Data.
:param manager: Manager.
:param server: Server.
:param driver: Driver.
:param conn: Connection.
:param _file: File.
:param filepath: File.
:return: args list.
"""
args = []
Expand Down Expand Up @@ -347,11 +347,58 @@ def _set_args_param_values(data, manager, server, driver, conn, _file):
False)
set_multiple('indexes', '--index', data, args, driver, conn, False)

args.append(fs_short_path(_file))
args.append(fs_short_path(filepath))

return args


def get_sql_util_args(data, manager, server, filepath):
"""
add args to the list.
:param data: Data.
:param manager: Manager.
:param server: Server.
:param driver: Driver.
:param conn: Connection.
:param filepath: File.
:return: args list.
"""
args = [
'--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, '--dbname',
data['database'],
'--file', fs_short_path(filepath)
]

return args


def use_restore_utility(data, manager, server, driver, conn, filepath):
utility = manager.utility('restore')
ret_val = does_utility_exist(utility)
if ret_val:
return ret_val, None, None

args = get_restore_util_args(data, manager, server, driver, conn, filepath)

return None, utility, args


def use_sql_utility(data, manager, server, filepath):
utility = manager.utility('sql')
ret_val = does_utility_exist(utility)
if ret_val:
return ret_val, None, None

args = get_sql_util_args(data, manager, server, filepath)

return None, utility, args


@blueprint.route('/job/<int:sid>', methods=['POST'], endpoint='create_job')
@pga_login_required
def create_restore_job(sid):
Expand All @@ -364,24 +411,27 @@ def create_restore_job(sid):
Returns:
None
"""
is_error, errmsg, data, _file = _get_create_req_data()
is_error, errmsg, data, filepath = _get_create_req_data()
if is_error:
return errmsg

is_error, errmsg, driver, manager, conn, _, server = _connect_server(sid)
if is_error:
return errmsg

utility = manager.utility('restore')
ret_val = does_utility_exist(utility)
if ret_val:
if data['format'] == 'plain':
error_msg, utility, args = use_sql_utility(
data, manager, server, filepath)
else:
error_msg, utility, args = use_restore_utility(
data, manager, server, driver, conn, filepath)

if error_msg is not None:
return make_json_response(
success=0,
errormsg=ret_val
errormsg=error_msg
)

args = _set_args_param_values(data, manager, server, driver, conn, _file)

try:
p = BatchProcess(
desc=RestoreMessage(
Expand Down
3 changes: 2 additions & 1 deletion web/pgadmin/tools/restore/static/js/restore.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ define('tools.restore', [
()=>getRestoreDisableOptionSchema({nodeInfo: treeNodeInfo}),
()=>getRestoreMiscellaneousSchema({nodeInfo: treeNodeInfo}),
{
role: ()=>getNodeListByName('role', treeNodeInfo, itemNodeData)
role: ()=>getNodeListByName('role', treeNodeInfo, itemNodeData),
nodeType: itemNodeData._type,
},
treeNodeInfo,
pgBrowser
Expand Down
Loading

0 comments on commit 73a55e0

Please sign in to comment.