diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js
index 29c11c2e..8c0f9a5a 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,38 @@ 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,
+            },
+            bracketPos = newData.label.lastIndexOf('(');
+
+          /* Strip the bracket */
+          newData.label = newData.label.substr(0, bracketPos);
+          let dropVal = pgadminUtils.fully_qualify(b, newData, item);
+          dropVal = dropVal + '()';
+
+          let curPos = dropVal.length;
+          /* If it has params */
+          if(data.label.substr(bracketPos).length > 2) {
+            curPos = curPos - 1;
+          }
+          return {
+            text: dropVal,
+            cur: {
+              from: curPos, to: 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..5c908afb 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,50 @@ export function getGCD(inp_arr) {
 export function getMod(no, divisor) {
   return ((no % divisor) + divisor) % divisor;
 }
+
+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) {
+    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..7df78d29 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 } from 'sources/utils';
 
 describe('getEpoch', function () {
   it('should return non zero', function () {
@@ -51,3 +51,20 @@ 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');
+  });
+});
