diff --git a/docs/en_US/tree_control.rst b/docs/en_US/tree_control.rst
index 73eb114f..03d4f1ca 100644
--- a/docs/en_US/tree_control.rst
+++ b/docs/en_US/tree_control.rst
@@ -19,6 +19,12 @@ view:
   control.
 * Click the minus sign (-) to the left of a node to close that node.
 
+You can also **drag and drop** certain object names to the query tool which
+is very helpful to save time in typing long object names. The text on drop will be
+fully qualified with schema name. Double quotes will be added to the text if required.
+For functions and procedures, the function name along with parameter names will
+be pasted in the query tool.
+
 Access context-sensitive menus by right-clicking on a node of the tree control
 to perform common tasks. Menus display options that include one or more of the
 following selections (options appear in alphabetical order):
diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js
index 29c11c2e..38252887 100644
--- a/web/pgadmin/browser/static/js/browser.js
+++ b/web/pgadmin/browser/static/js/browser.js
@@ -12,7 +12,7 @@ define('pgadmin.browser', [
   'sources/gettext', 'sources/url_for', 'require', 'jquery', 'underscore', 'underscore.string',
   'bootstrap', 'sources/pgadmin', 'pgadmin.alertifyjs', 'bundled_codemirror',
   'sources/check_node_visibility', './toolbar', 'pgadmin.help',
-  'sources/csrf', 'pgadmin.browser.utils',
+  'sources/csrf', 'sources/utils', 'pgadmin.browser.utils',
   'wcdocker', 'jquery.contextmenu', 'jquery.aciplugin', 'jquery.acitree',
   'pgadmin.browser.preferences', 'pgadmin.browser.messages',
   'pgadmin.browser.menu', 'pgadmin.browser.panel', 'pgadmin.browser.layout',
@@ -24,7 +24,7 @@ define('pgadmin.browser', [
   tree,
   gettext, url_for, require, $, _, S,
   Bootstrap, pgAdmin, Alertify, codemirror,
-  checkNodeVisibility, toolBar, help, csrfToken
+  checkNodeVisibility, toolBar, help, csrfToken, pgadminUtils,
 ) {
   window.jQuery = window.$ = $;
   // Some scripts do export their object in the window only.
@@ -102,6 +102,46 @@ define('pgadmin.browser', [
 
       b.tree = $('#tree').aciTree('api');
       b.treeMenu.register($('#tree'));
+
+      b.treeMenu.registerDraggableType({
+        'table partition type sequence package view mview foreign_table edbvar' : (data, item)=>{
+          return pgadminUtils.fully_qualify(b, data, item);
+        },
+        'schema column' : (data)=>{
+          return pgadminUtils.quote_ident(data._label);
+        },
+        'edbfunc function edbproc procedure' : (data, item)=>{
+          let newData = {...data},
+            parsedFunc = null,
+            dropVal = '',
+            curPos = {from: 0, to: 0};
+
+          parsedFunc = pgadminUtils.parseFuncParams(newData._label);
+          newData._label = parsedFunc.func_name;
+          dropVal = pgadminUtils.fully_qualify(b, newData, item);
+
+          if(parsedFunc.params.length > 0) {
+            dropVal = dropVal + '(';
+            curPos.from =  dropVal.length;
+            dropVal = dropVal + parsedFunc.params[0][0];
+            curPos.to = dropVal.length;
+
+            for(let i=1; i<parsedFunc.params.length; i++) {
+              dropVal = dropVal + ', ' + parsedFunc.params[i][0];
+            }
+
+            dropVal = dropVal + ')';
+          } else {
+            dropVal = dropVal + '()';
+            curPos.from = curPos.to = dropVal.length + 1;
+          }
+
+          return {
+            text: dropVal,
+            cur: curPos,
+          };
+        },
+      });
     };
 
   // Extend the browser class attributes
diff --git a/web/pgadmin/static/js/tree/tree.js b/web/pgadmin/static/js/tree/tree.js
index 782f4d59..99397ef4 100644
--- a/web/pgadmin/static/js/tree/tree.js
+++ b/web/pgadmin/static/js/tree/tree.js
@@ -8,6 +8,7 @@
 //////////////////////////////////////////////////////////////////////////
 
 import {isValidData} from 'sources/utils';
+import $ from 'jquery';
 
 export class TreeNode {
   constructor(id, data, domNode, parent) {
@@ -97,6 +98,87 @@ export class Tree {
   constructor() {
     this.rootNode = new TreeNode(undefined, {});
     this.aciTreeApi = undefined;
+    this.draggableTypes = {};
+  }
+
+  /*
+   *
+   * The dropDetailsFunc should return an object of sample
+   * {text: 'xyz', cur: {from:0, to:0} where text is the drop text and
+   * cur is selection range of text after dropping. If returned as
+   * string, by default cursor will be set to the end of text
+   */
+  registerDraggableType(typeOrTypeDict, dropDetailsFunc=null) {
+    if(typeof typeOrTypeDict == 'object') {
+      Object.keys(typeOrTypeDict).forEach((type)=>{
+        this.registerDraggableType(type, typeOrTypeDict[type]);
+      });
+    } else {
+      if(dropDetailsFunc != null) {
+        typeOrTypeDict.replace(/ +/, ' ').split(' ').forEach((type)=>{
+          this.draggableTypes[type] = dropDetailsFunc;
+        });
+      }
+    }
+  }
+
+  getDraggable(type) {
+    if(this.draggableTypes[type]) {
+      return this.draggableTypes[type];
+    } else {
+      return null;
+    }
+  }
+
+  prepareDraggable(data, item) {
+    let dropDetailsFunc = this.getDraggable(data._type);
+
+    if(dropDetailsFunc != null) {
+      item.find('.aciTreeItem')
+        .attr('draggable', true)
+        .on('dragstart', (e)=> {
+          let dropDetails = dropDetailsFunc(data, item);
+          let origEvent = e.originalEvent;
+
+          if(typeof dropDetails == 'string') {
+            dropDetails = {
+              text:dropDetails,
+              cur:{
+                from:dropDetails.length,
+                to: dropDetails.length,
+              },
+            };
+          } else {
+            if(!dropDetails.cur) {
+              dropDetails = {
+                ...dropDetails,
+                cur:{
+                  from:dropDetails.text.length,
+                  to: dropDetails.text.length,
+                },
+              };
+            }
+          }
+
+          origEvent.dataTransfer.setData('text', JSON.stringify(dropDetails));
+
+          /* setDragImage is not supported in IE. We leave it to
+           * its default look and feel
+           */
+          if(origEvent.dataTransfer.setDragImage) {
+            let dragItem = $(`
+              <div class="drag-tree-node">
+                <span>${dropDetails.text}</span>
+              </div>`
+            );
+
+            $('body .drag-tree-node').remove();
+            $('body').append(dragItem);
+
+            origEvent.dataTransfer.setDragImage(dragItem[0], 0, 0);
+          }
+        });
+    }
   }
 
   addNewNode(id, data, domNode, parentPath) {
@@ -163,6 +245,9 @@ export class Tree {
         if (eventName === 'added') {
           const id = api.getId(item);
           const data = api.itemData(item);
+
+          this.prepareDraggable(data, item);
+
           const parentId = this.translateTreeNodeIdFromACITree(api.parent(item));
           this.addNewNode(id, data, item, parentId);
         }
diff --git a/web/pgadmin/static/js/utils.js b/web/pgadmin/static/js/utils.js
index 1c58a9eb..fe9fd8ed 100644
--- a/web/pgadmin/static/js/utils.js
+++ b/web/pgadmin/static/js/utils.js
@@ -8,6 +8,7 @@
 //////////////////////////////////////////////////////////////////////////
 
 import _ from 'underscore';
+import { getTreeNodeHierarchyFromIdentifier } from 'sources/tree/pgadmin_tree_node';
 
 export function parseShortcutValue(obj) {
   var shortcut = '';
@@ -83,3 +84,118 @@ export function getGCD(inp_arr) {
 export function getMod(no, divisor) {
   return ((no % divisor) + divisor) % divisor;
 }
+
+export function parseFuncParams(label) {
+  let paramArr = [],
+    funcName = '',
+    paramStr = '';
+
+  if(label.endsWith('()')) {
+    funcName = label.substring(0, label.length-2);
+  } else if(!label.endsWith(')')) {
+    funcName = label;
+  } else if(!label.endsWith('()') && label.endsWith(')')) {
+    let i = 0,
+      startBracketPos = label.length;
+
+    /* Parse through the characters in reverse to find the param start bracket */
+    i = label.length-2;
+    while(i >= 0) {
+      if(label[i] == '(') {
+        startBracketPos = i;
+        break;
+      } else if(label[i] == '"') {
+        /* If quotes, skip all the chars till next quote */
+        i--;
+        while(label[i] != '"') i--;
+      }
+      i--;
+    }
+
+    funcName = label.substring(0, startBracketPos);
+    paramStr = label.substring(startBracketPos+1, label.length-1);
+
+    let paramStart = 0,
+      paramName = '',
+      paramModes = ['IN', 'OUT', 'INOUT', 'VARIADIC'];
+
+    paramStart = i = 0;
+    while(i < paramStr.length) {
+      if(paramStr[i] == '"') {
+        /* If quotes, skip all the chars till next quote */
+        i++;
+        while(paramStr[i] != '"') i++;
+      } else if (paramStr[i] == ' ') {
+        /* if paramName is already set, ignore till comma
+         * Or if paramName is parsed as one of the modes, reset.
+         */
+        if(paramName == '' || paramModes.indexOf(paramName) > -1 ) {
+          paramName = paramStr.substring(paramStart, i);
+          paramStart = i+1;
+        }
+      }
+      else if (paramStr[i] == ',') {
+        paramArr.push([paramName, paramStr.substring(paramStart, i)]);
+        paramName = '';
+        paramStart = i+1;
+      }
+      i++;
+    }
+    paramArr.push([paramName, paramStr.substring(paramStart)]);
+  }
+
+  return {
+    'func_name': funcName,
+    'param_string': paramStr,
+    'params': paramArr,
+  };
+}
+
+export function quote_ident(value) {
+  /* check if the string is number or not */
+  let quoteIt = false;
+  if (!isNaN(parseInt(value))){
+    quoteIt = true;
+  }
+
+  if(value.search(/[^a-z0-9_]/g) > -1) {
+    /* escape double quotes */
+    value = value.replace(/"/g, '""');
+    quoteIt = true;
+  }
+
+  if(quoteIt) {
+    return `"${value}"`;
+  } else {
+    return value;
+  }
+}
+
+export function fully_qualify(pgBrowser, data, item) {
+  const parentData = getTreeNodeHierarchyFromIdentifier.call(pgBrowser, item);
+  let namespace = '';
+
+  if (parentData.schema !== undefined) {
+    namespace = quote_ident(parentData.schema._label);
+  }
+  else if (parentData.view !== undefined) {
+    namespace = quote_ident(parentData.view._label);
+  }
+  else if (parentData.catalog !== undefined) {
+    namespace = quote_ident(parentData.catalog._label);
+  }
+
+  if (parentData.package !== undefined && data._type != 'package') {
+    if(namespace == '') {
+      namespace = quote_ident(parentData.package._label);
+    } else {
+      namespace += '.' + quote_ident(parentData.package._label);
+    }
+  }
+
+  if(namespace != '') {
+    return namespace + '.' + quote_ident(data._label);
+  } else {
+    return quote_ident(data._label);
+  }
+}
diff --git a/web/pgadmin/static/scss/_pgadmin.style.scss b/web/pgadmin/static/scss/_pgadmin.style.scss
index ed426545..f5a8877c 100644
--- a/web/pgadmin/static/scss/_pgadmin.style.scss
+++ b/web/pgadmin/static/scss/_pgadmin.style.scss
@@ -983,3 +983,15 @@ table.table-empty-rows{
   padding: 0px !important;
   position: absolute;
 }
+
+.drag-tree-node {
+  position: absolute;
+  top:-100px;
+  left:0;
+  z-index: 99999;
+  color: $input-focus-color;
+  background: $input-bg;
+  border: $input-border-width solid $input-focus-border-color;
+  border-radius: $input-border-radius;
+  padding: $input-btn-padding-y $input-btn-padding-x;
+}
diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
index a8560574..ef468f63 100644
--- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
@@ -341,8 +341,31 @@ define('tools.querytool', [
         gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
         extraKeys: pgBrowser.editor_shortcut_keys,
         scrollbarStyle: 'simple',
+        dragDrop: false,
       });
 
+      if(self.handler.is_query_tool) {
+        self.query_tool_obj.setOption('dragDrop', true);
+        self.query_tool_obj.on('drop', (editor, e) => {
+          var cursor = editor.coordsChar({
+            left: e.x,
+            top: e.y,
+          });
+          var dropDetails = JSON.parse(e.dataTransfer.getData('text'));
+          e.codemirrorIgnore = true;
+          e.dataTransfer.clearData('text');
+          editor.replaceRange(dropDetails.text, cursor);
+          editor.focus();
+          editor.setSelection({
+            ...cursor,
+            ch: cursor.ch + dropDetails.cur.from,
+          },{
+            ...cursor,
+            ch: cursor.ch +dropDetails.cur.to,
+          });
+        });
+      }
+
       pgBrowser.Events.on('pgadmin:query_tool:sql_panel:focus', ()=>{
         self.query_tool_obj.focus();
       });
diff --git a/web/regression/javascript/pgadmin_utils_spec.js b/web/regression/javascript/pgadmin_utils_spec.js
index 02bd5478..bc1959a4 100644
--- a/web/regression/javascript/pgadmin_utils_spec.js
+++ b/web/regression/javascript/pgadmin_utils_spec.js
@@ -7,7 +7,7 @@
 //
 //////////////////////////////////////////////////////////////
 
-import { getEpoch, getGCD, getMod } from 'sources/utils';
+import { getEpoch, getGCD, getMod, quote_ident, parseFuncParams } from 'sources/utils';
 
 describe('getEpoch', function () {
   it('should return non zero', function () {
@@ -51,3 +51,87 @@ describe('getMod', function () {
     expect(getMod(-7,5)).toEqual(3);
   });
 });
+
+describe('quote_ident', function () {
+  it('normal string', function () {
+    expect(quote_ident('abcd')).toEqual('abcd');
+  });
+
+  it('contains certain characters string', function () {
+    expect(quote_ident('Abcd')).toEqual('"Abcd"');
+    expect(quote_ident('abc$d')).toEqual('"abc$d"');
+    expect(quote_ident('ab cd')).toEqual('"ab cd"');
+  });
+
+  it('starts with number', function () {
+    expect(quote_ident('1a')).toEqual('"1a"');
+    expect(quote_ident('a1')).toEqual('a1');
+  });
+});
+
+describe('parseFuncParams', function () {
+  let funcLabel = '',
+    expectedObj = {};
+
+  it('function with params', function () {
+    funcLabel = 'func1(a integer, b text)';
+    expectedObj = {
+      'func_name': 'func1',
+      'param_string': 'a integer, b text',
+      'params': [
+        ['a', 'integer'],
+        ['b', 'text'],
+      ],
+    };
+    expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
+  });
+
+  it('function without params', function () {
+    funcLabel = 'func1()';
+    expectedObj = {
+      'func_name': 'func1',
+      'param_string': '',
+      'params': [],
+    };
+    expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
+  });
+
+  it('function name special chars', function () {
+    funcLabel = 'fun(c1(a integer, b text)';
+    expectedObj = {
+      'func_name': 'fun(c1',
+      'param_string': 'a integer, b text',
+      'params': [
+        ['a', 'integer'],
+        ['b', 'text'],
+      ],
+    };
+    expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
+  });
+
+  it('function params special chars', function () {
+    funcLabel = 'func1("a(b" integer, "a b" text)';
+    expectedObj = {
+      'func_name': 'func1',
+      'param_string': '"a(b" integer, "a b" text',
+      'params': [
+        ['"a(b"', 'integer'],
+        ['"a b"', 'text'],
+      ],
+    };
+    expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
+  });
+
+  it('function params with modes', function () {
+    funcLabel = 'func1(IN a integer, OUT b text)';
+    expectedObj = {
+      'func_name': 'func1',
+      'param_string': 'IN a integer, OUT b text',
+      'params': [
+        ['a', 'integer'],
+        ['b', 'text'],
+      ],
+    };
+    expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
+  });
+});
