Index: web/pgadmin/tools/sqleditor/static/js/sqleditor.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- web/pgadmin/tools/sqleditor/static/js/sqleditor.js	(revision 89fa85d650674cdab9fa5765e02d7727bca7f4fa)
+++ web/pgadmin/tools/sqleditor/static/js/sqleditor.js	(date 1596189426656)
@@ -140,6 +140,9 @@
       // Indentation options
       'click #btn-indent-code': 'on_indent_code',
       'click #btn-unindent-code': 'on_unindent_code',
+      // Format
+      'click #btn-format-sql': 'on_format_sql',
+      // Transaction control
       'click #btn-commit': 'on_commit_transaction',
       'click #btn-rollback': 'on_rollback_transaction',
     },
@@ -1742,6 +1745,16 @@
         self.handler
       );
     },
+
+    on_format_sql: function() {
+      var self = this;
+      // Trigger the format signal to the SqlEditorController class
+      self.handler.trigger(
+        'pgadmin-sqleditor:format_sql',
+        self,
+        self.handler
+      );
+    },
 
     // Callback function for the clear button click.
     on_clear: function(ev) {
@@ -2401,6 +2414,8 @@
         // Indentation related
         self.on('pgadmin-sqleditor:indent_selected_code', self._indent_selected_code, self);
         self.on('pgadmin-sqleditor:unindent_selected_code', self._unindent_selected_code, self);
+        // Format
+        self.on('pgadmin-sqleditor:format_sql', self._format_sql, self);
 
         window.parent.$(window.parent.document).on('pgadmin-sqleditor:rows-copied', self._copied_in_other_session);
       },
@@ -4235,6 +4250,28 @@
         editor.execCommand('indentLess');
       },
 
+      /*
+       * This function will format the SQL
+       */
+      _format_sql: function() {
+        var self = this,
+          editor = self.gridView.query_tool_obj;
+
+        $.ajax({
+          url: url_for('sql.format'),
+          data: JSON.stringify({'sql': editor.getValue()}),
+          method: 'POST',
+          contentType: 'application/json',
+          dataType: 'json',
+        })
+          .done(function(res) {
+            editor.setValue(res.data.sql);
+          })
+          .fail(function() {
+          /* failure should be ignored */
+          });
+      },
+
       isQueryRunning: function() {
         return is_query_running;
       },
Index: web/pgadmin/misc/sql/__init__.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- web/pgadmin/misc/sql/__init__.py	(revision 89fa85d650674cdab9fa5765e02d7727bca7f4fa)
+++ web/pgadmin/misc/sql/__init__.py	(date 1596193559642)
@@ -9,8 +9,12 @@
 
 """A blueprint module providing utility functions for the application."""
 
-from flask import url_for
+import sqlparse
+from flask import request, url_for
+from flask_security import login_required
 from pgadmin.utils import PgAdminModule
+from pgadmin.utils.ajax import make_json_response
+from pgadmin.utils.preferences import Preferences
 
 MODULE_NAME = 'sql'
 
@@ -24,5 +28,62 @@
         }]
 
 
+    def get_exposed_url_endpoints(self):
+        """
+        Returns:
+            list: URL endpoints
+        """
+        return [
+            'sql.format', 'sql.format'
+        ]
+
+
 # Initialise the module
 blueprint = SQLModule(MODULE_NAME, __name__, url_prefix='/misc/sql')
+
+
+def sql_format(sql):
+    """
+    This function takes a SQL statement, formats it, and returns it
+    """
+    p = Preferences.module('sqleditor')
+    output = sqlparse.format(sql,
+                           keyword_case=p.preference(
+                               'keyword_case').get(),
+                           identifier_case=p.preference(
+                               'identifier_case').get(),
+                           strip_comments=p.preference(
+                               'strip_comments').get(),
+                           reindent=p.preference(
+                               'reindent').get(),
+                           reindent_aligned=p.preference(
+                               'reindent_aligned').get(),
+                           use_space_around_operators=p.preference(
+                               'spaces_around_operators').get(),
+                           comma_first=p.preference(
+                               'comma_first').get(),
+                           wrap_after=p.preference(
+                               'wrap_after').get(),
+                           indent_tabs=not p.preference(
+                               'use_spaces').get(),
+                           indent_width=p.preference(
+                               'tab_size').get())
+
+    return output
+
+
+@blueprint.route("/format", methods=['POST'], endpoint="format")
+@login_required
+def sql_format_wrapper():
+    """
+    This endpoint takes a SQL statement, formats it, and returns it
+    """
+    sql = ''
+    if request.data:
+        sql = sql_format(request.get_json()['sql'])
+
+    return make_json_response(
+        data={'sql': sql},
+        status=200
+    )
+
Index: web/pgadmin/tools/datagrid/templates/datagrid/index.html
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- web/pgadmin/tools/datagrid/templates/datagrid/index.html	(revision 89fa85d650674cdab9fa5765e02d7727bca7f4fa)
+++ web/pgadmin/tools/datagrid/templates/datagrid/index.html	(date 1596034119290)
@@ -189,6 +189,12 @@
                                  {{ _(' (Shift+Ctrl+/)') }}{%- endif %}</span>
                         </a>
                     </li>
+                    <li class="dropdown-divider"></li>
+                    <li>
+                        <a class="dropdown-item" id="btn-format-sql" href="#" tabindex="0">
+                            <span>{{ _('Format SQL') }}</span>
+                        </a>
+                    </li>
                 </ul>
             </div>
             <div class="btn-group mr-1" role="group" aria-label="">
Index: web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py	(revision 89fa85d650674cdab9fa5765e02d7727bca7f4fa)
+++ web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py	(date 1596190518606)
@@ -169,27 +169,6 @@
         )
     )
 
-    self.tab_size = self.preference.register(
-        'Editor', 'tab_size',
-        gettext("Tab size"), 'integer', 4,
-        min_val=2,
-        max_val=8,
-        category_label=gettext('Options'),
-        help_str=gettext(
-            'The number of spaces per tab. Minimum 2, maximum 8.'
-        )
-    )
-
-    self.use_spaces = self.preference.register(
-        'Editor', 'use_spaces',
-        gettext("Use spaces?"), 'boolean', False,
-        category_label=gettext('Options'),
-        help_str=gettext(
-            'Specifies whether or not to insert spaces instead of tabs '
-            'when the tab key or auto-indent are used.'
-        )
-    )
-
     self.wrap_code = self.preference.register(
         'Editor', 'wrap_code',
         gettext("Line wrapping?"), 'boolean', False,
@@ -703,3 +682,98 @@
         category_label=gettext('Keyboard shortcuts'),
         fields=shortcut_fields
     )
+
+    # Register options for SQL formatting
+    self.keyword_case = self.preference.register(
+        'editor', 'keyword_case',
+        gettext("Keyword case"), 'radioModern', 'upper',
+        options=[{'label': 'Upper case', 'value': 'upper'},
+                 {'label': 'Lower case', 'value': 'lower'},
+                 {'label': 'Capitalized', 'value': 'capitalize'}],
+        category_label=gettext('SQL Formatting'),
+        help_str=gettext(
+            'Convert keywords to upper, lower, or capitalized casing.'
+        )
+    )
+
+    self.identifier_case = self.preference.register(
+        'editor', 'identifier_case',
+        gettext("Identifier case"), 'radioModern', 'upper',
+        options=[{'label': 'Upper case', 'value': 'upper'},
+                 {'label': 'Lower case', 'value': 'lower'},
+                 {'label': 'Capitalized', 'value': 'capitalize'}],
+        category_label=gettext('SQL Formatting'),
+        help_str=gettext(
+            'Convert identifiers to upper, lower, or capitalized casing.'
+        )
+    )
+
+    self.strip_comments = self.preference.register(
+        'editor', 'strip_comments',
+        gettext("Strip comments?"), 'boolean', False,
+        category_label=gettext('SQL Formatting'),
+        help_str=gettext('If set to True, comments will be removed.')
+    )
+
+    self.reindent = self.preference.register(
+        'editor', 'reindent',
+        gettext("Re-indent?"), 'boolean', True,
+        category_label=gettext('SQL Formatting'),
+        help_str=gettext('If set to True, the indentations of the '
+                         'statements are changed.')
+    )
+
+    self.reindent_aligned = self.preference.register(
+        'editor', 'reindent_aligned',
+        gettext("Re-indent aligned?"), 'boolean', False,
+        category_label=gettext('SQL Formatting'),
+        help_str=gettext('If set to True, the indentations of the '
+                         'statements are changed, and statements are '
+                         'aligned by keywords.')
+    )
+
+    self.spaces_around_operators = self.preference.register(
+        'editor', 'spaces_around_operators',
+        gettext("Spaces around operators?"), 'boolean', True,
+        category_label=gettext('SQL Formatting'),
+        help_str=gettext('If set to True, spaces are used around all '
+                         'operators.')
+    )
+
+    self.comma_first = self.preference.register(
+        'editor', 'comma_first',
+        gettext("Comma-first notation?"), 'boolean', False,
+        category_label=gettext('SQL Formatting'),
+        help_str=gettext('If set to True, comma-first notation for column '
+                         'names is used.')
+    )
+
+    self.wrap_after = self.preference.register(
+        'editor', 'wrap_after',
+        gettext("Wrap after N characters"), 'integer', 4,
+        category_label=gettext('SQL Formatting'),
+        help_str=gettext("The column limit (in characters) for wrapping "
+                         "comma-separated lists. If zero, it puts "
+                         "every item in the list on its own line.")
+    )
+
+    self.tab_size = self.preference.register(
+        'editor', 'tab_size',
+        gettext("Tab size"), 'integer', 4,
+        min_val=2,
+        max_val=8,
+        category_label=gettext('SQL Formatting'),
+        help_str=gettext(
+            'The number of spaces per tab. Minimum 2, maximum 8.'
+        )
+    )
+
+    self.use_spaces = self.preference.register(
+        'editor', 'use_spaces',
+        gettext("Use spaces?"), 'boolean', False,
+        category_label=gettext('SQL Formatting'),
+        help_str=gettext(
+            'Specifies whether or not to insert spaces instead of tabs '
+            'when the tab key or auto-indent are used.'
+        )
+    )
