diff --git a/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js b/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js
index 1645416..af97e84 100644
--- a/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js
+++ b/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js
@@ -110,11 +110,11 @@
 
     // When text editor opens
     this.loadValue = function (item) {
-      if (item[args.column.field] === "") {
+      if (item[args.column.pos] === "") {
         $input.val("''");
       }
       else {
-        $input.val(defaultValue = item[args.column.field]);
+        $input.val(defaultValue = item[args.column.pos]);
         $input.select();
       }
     };
@@ -141,7 +141,7 @@
     };
 
     this.applyValue = function (item, state) {
-      item[args.column.field] = state;
+      item[args.column.pos] = state;
     };
 
     this.isValueChanged = function () {
@@ -252,7 +252,7 @@
     };
 
     this.loadValue = function (item) {
-      var data = defaultValue = item[args.column.field];
+      var data = defaultValue = item[args.column.pos];
       if (typeof data === "object" && !Array.isArray(data)) {
         data = JSON.stringify(data);
       } else if (Array.isArray(data)) {
@@ -278,7 +278,7 @@
     };
 
     this.applyValue = function (item, state) {
-      item[args.column.field] = state;
+      item[args.column.pos] = state;
     };
 
     this.isValueChanged = function () {
@@ -385,7 +385,7 @@
     };
 
     this.loadValue = function (item) {
-      $input.val(defaultValue = item[args.column.field]);
+      $input.val(defaultValue = item[args.column.pos]);
       $input.select();
     };
 
@@ -394,7 +394,7 @@
     };
 
     this.applyValue = function (item, state) {
-      item[args.column.field] = state;
+      item[args.column.pos] = state;
     };
 
     this.isValueChanged = function () {
@@ -468,12 +468,12 @@
     };
 
     this.loadValue = function (item) {
-      defaultValue = item[args.column.field];
+      defaultValue = item[args.column.pos];
       if (_.isNull(defaultValue)) {
         $select.prop('indeterminate', true);
       }
       else {
-        defaultValue = !!item[args.column.field];
+        defaultValue = !!item[args.column.pos];
         if (defaultValue) {
           $select.prop('checked', true);
         } else {
@@ -490,7 +490,7 @@
     };
 
     this.applyValue = function (item, state) {
-      item[args.column.field] = state;
+      item[args.column.pos] = state;
     };
 
     this.isValueChanged = function () {
@@ -590,7 +590,7 @@
     };
 
     this.loadValue = function (item) {
-      var data = defaultValue = item[args.column.field];
+      var data = defaultValue = item[args.column.pos];
       if (typeof data === "object" && !Array.isArray(data)) {
         data = JSON.stringify(data);
       } else if (Array.isArray(data)) {
@@ -613,7 +613,7 @@
     };
 
     this.applyValue = function (item, state) {
-      item[args.column.field] = state;
+      item[args.column.pos] = state;
     };
 
     this.isValueChanged = function () {
@@ -667,7 +667,7 @@
     };
 
     this.loadValue = function (item) {
-      var value = item[args.column.field];
+      var value = item[args.column.pos];
 
       // Check if value is null or undefined
       if (value === undefined && typeof value === "undefined") {
@@ -819,7 +819,7 @@
     };
 
     this.loadValue = function (item) {
-      defaultValue = item[args.column.field];
+      defaultValue = item[args.column.pos];
       $input.val(defaultValue);
       $input[0].defaultValue = defaultValue;
       $input.select();
@@ -833,7 +833,7 @@
     };
 
     this.applyValue = function (item, state) {
-      item[args.column.field] = state;
+      item[args.column.pos] = state;
     };
 
     this.isValueChanged = function () {
diff --git a/web/pgadmin/tools/debugger/__init__.py b/web/pgadmin/tools/debugger/__init__.py
index 9848b10..0921da1 100644
--- a/web/pgadmin/tools/debugger/__init__.py
+++ b/web/pgadmin/tools/debugger/__init__.py
@@ -881,7 +881,7 @@ def messages(trans_id):
     port_number = ''
 
     if conn.connected():
-        status, result, my_result = conn.poll()
+        status, result = conn.poll()
         notify = conn.messages()
         if notify:
             # In notice message we need to find "PLDBGBREAK" string to find the port number to attach.
@@ -1363,7 +1363,8 @@ def poll_end_execution_result(trans_id):
         statusmsg = conn.status_message()
         if statusmsg and statusmsg == 'SELECT 1':
             statusmsg = ''
-        status, result, col_info = conn.poll()
+        status, result = conn.poll()
+        col_info = conn.get_column_info()
         if status == ASYNC_OK and \
                 not session['functionData'][str(trans_id)]['is_func'] and \
                 session['functionData'][str(trans_id)]['language'] == 'edbspl':
@@ -1405,6 +1406,21 @@ def poll_end_execution_result(trans_id):
                         column['type_code'] = items[1][1]
                         columns.append(column)
 
+                # We need to convert result from 2D array to dict for BackGrid
+                # BackGrid do not support for 2D array result as it it Backbone Model based grid
+                # This Conversion is not an overhead as most of the time
+                # result will be smaller
+                _tmp_result = []
+                for row in result:
+                    temp = dict()
+                    count = 0
+                    for item in row:
+                        temp[columns[count]['name']] = item
+                        count += 1
+                    _tmp_result.append(temp)
+                # Replace 2d array with dict result
+                result = _tmp_result
+
                 return make_json_response(success=1, info=gettext("Execution Completed."),
                                           data={'status': status, 'result': result,
                                                 'col_info': columns, 'status_message': statusmsg})
@@ -1453,7 +1469,7 @@ def poll_result(trans_id):
     conn = manager.connection(did=obj['database_id'], conn_id=obj['exe_conn_id'])
 
     if conn.connected():
-        status, result, my_result = conn.poll()
+        status, result = conn.poll()
         if status == ASYNC_OK and result is not None:
             status = 'Success'
         else:
diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py
index 2cad508..0d38c15 100644
--- a/web/pgadmin/tools/sqleditor/__init__.py
+++ b/web/pgadmin/tools/sqleditor/__init__.py
@@ -420,6 +420,43 @@ def preferences(trans_id):
         return success_return()
 
 
+@blueprint.route('/columns/<int:trans_id>', methods=["GET"])
+@login_required
+def get_columns(trans_id):
+    """
+    This method will returns list of columns of last async query.
+
+    Args:
+        trans_id: unique transaction id
+    """
+    columns = dict()
+    columns_info = None
+    primary_keys = None
+    status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+    if status and conn is not None and session_obj is not None:
+        # Check PK column info is available or not
+        if 'primary_keys' in session_obj:
+            primary_keys = session_obj['primary_keys']
+
+        # Fetch column information
+        columns_info = conn.get_column_info()
+        if columns_info is not None:
+            for col in columns_info:
+                col_type = dict()
+                col_type['type_code'] = col['type_code']
+                col_type['type_name'] = None
+                columns[col['name']] = col_type
+
+        # As we changed the transaction object we need to
+        # restore it and update the session variable.
+        session_obj['columns_info'] = columns
+        update_session_grid_transaction(trans_id, session_obj)
+
+    return make_json_response(data={'status': True,
+                                    'columns': columns_info,
+                                    'primary_keys': primary_keys})
+
+
 @blueprint.route('/poll/<int:trans_id>', methods=["GET"])
 @login_required
 def poll(trans_id):
@@ -429,20 +466,19 @@ def poll(trans_id):
     Args:
         trans_id: unique transaction id
     """
-    col_info = None
     result = None
-    primary_keys = None
     rows_affected = 0
     additional_result = []
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
     if status and conn is not None and session_obj is not None:
-        status, result, col_info = conn.poll()
+        status, result = conn.poll()
         if status == ASYNC_OK:
             status = 'Success'
             if 'primary_keys' in session_obj:
                 primary_keys = session_obj['primary_keys']
+            rows_affected = conn.rows_affected()
 
             # if transaction object is instance of QueryToolCommand
             # and transaction aborted for some reason then issue a
@@ -464,22 +500,6 @@ def poll(trans_id):
         status = 'NotConnected'
         result = error_msg
 
-    # Check column info is available or not
-    if col_info is not None and len(col_info) > 0:
-        columns = dict()
-        rows_affected = conn.rows_affected()
-
-        for col in col_info:
-            col_type = dict()
-            col_type['type_code'] = col['type_code']
-            col_type['type_name'] = None
-            columns[col['name']] = col_type
-
-        # As we changed the transaction object we need to
-        # restore it and update the session variable.
-        session_obj['columns_info'] = columns
-        update_session_grid_transaction(trans_id, session_obj)
-
     """
         Procedure/Function output may comes in the form of Notices from the
         database server, so we need to append those outputs with the
@@ -497,8 +517,6 @@ def poll(trans_id):
         else:
             result = additional_result
 
-        rows_affected = conn.rows_affected()
-
     # There may be additional messages even if result is present
     # eg: Function can provide result as well as RAISE messages
     additional_messages = None
@@ -510,7 +528,6 @@ def poll(trans_id):
     return make_json_response(
         data={
             'status': status, 'result': result,
-            'colinfo': col_info, 'primary_keys': primary_keys,
             'rows_affected': rows_affected,
             'additional_messages': additional_messages
         }
diff --git a/web/pgadmin/tools/sqleditor/command.py b/web/pgadmin/tools/sqleditor/command.py
index ecaceda..9420e08 100644
--- a/web/pgadmin/tools/sqleditor/command.py
+++ b/web/pgadmin/tools/sqleditor/command.py
@@ -418,6 +418,14 @@ class TableCommand(GridCommand):
         list_of_sql = []
         _rowid = None
 
+        # Replace column positions with names
+        def set_column_names(data):
+            new_data = {}
+            for key in data:
+                new_data[changed_data['columns'][int(key)]['name']] = data[key]
+
+            return new_data
+
         if conn.connected():
 
             # Start the transaction
@@ -425,8 +433,10 @@ class TableCommand(GridCommand):
 
             # Iterate total number of records to be updated/inserted
             for of_type in changed_data:
-
-                # if no data to be saved then continue
+                # No need to go further if its not add/update/delete operation
+                if of_type not in ('added', 'updated', 'deleted'):
+                    continue
+                # if no data to be save then continue
                 if len(changed_data[of_type]) < 1:
                     continue
 
@@ -434,10 +444,12 @@ class TableCommand(GridCommand):
                 if of_type == 'added':
                     for each_row in changed_data[of_type]:
                         data = changed_data[of_type][each_row]['data']
-                        data_type = changed_data[of_type][each_row]['data_type']
-                        list_of_rowid.append(data.get('__temp_PK'))
                         # Remove our unique tracking key
                         data.pop('__temp_PK', None)
+                        data = set_column_names(data)
+                        data_type = set_column_names(changed_data[of_type][each_row]['data_type'])
+                        list_of_rowid.append(data.get('__temp_PK'))
+
                         sql = render_template("/".join([self.sql_path, 'insert.sql']),
                                               data_to_be_saved=data,
                                               primary_keys=None,
@@ -449,9 +461,9 @@ class TableCommand(GridCommand):
                 # For updated rows
                 elif of_type == 'updated':
                     for each_row in changed_data[of_type]:
-                        data = changed_data[of_type][each_row]['data']
-                        pk = changed_data[of_type][each_row]['primary_keys']
-                        data_type = changed_data[of_type][each_row]['data_type']
+                        data = set_column_names(changed_data[of_type][each_row]['data'])
+                        pk = set_column_names(changed_data[of_type][each_row]['primary_keys'])
+                        data_type = set_column_names(changed_data[of_type][each_row]['data_type'])
                         sql = render_template("/".join([self.sql_path, 'update.sql']),
                                               data_to_be_saved=data,
                                               primary_keys=pk,
@@ -472,10 +484,22 @@ class TableCommand(GridCommand):
                         # Fetch the keys for SQL generation
                         if is_first:
                             # We need to covert dict_keys to normal list in Python3
-                            # In Python2, it's already a list
-                            keys = list(changed_data[of_type][each_row].keys())
+                            # In Python2, it's already a list & We will also fetch column names using index
+                            keys = [
+                                changed_data['columns'][int(k)]['name']
+                                       for k in list(changed_data[of_type][each_row].keys())
+                            ]
                             no_of_keys = len(keys)
                             is_first = False
+                    # Map index with column name for each row
+                    for row in rows_to_delete:
+                        for k, v in row.items():
+                            # Set primary key with label & delete index based mapped key
+                            try:
+                                row[keys[int(k)]] = v
+                            except ValueError:
+                                continue
+                            del row[k]
 
                     sql = render_template("/".join([self.sql_path, 'delete.sql']),
                                           data=rows_to_delete,
diff --git a/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js b/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js
index 82e8ebe..a2ef0ac 100644
--- a/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js
@@ -577,6 +577,15 @@ define(
            - We are using this event for Copy operation on grid
        */
 
+      // Get the item column value using a custom 'fieldIdx' column param
+      get_item_column_value: function (item, column) {
+        if (column.pos !== undefined) {
+          return item[column.pos];
+        } else {
+          return null;
+        }
+      },
+
       // This function is responsible to create and render the SlickGrid.
       render_grid: function(collection, columns, is_editable) {
         var self = this;
@@ -617,6 +626,7 @@ define(
         _.each(columns, function(c) {
             var options = {
               id: c.name,
+              pos: c.pos,
               field: c.name,
               name: c.label
             };
@@ -652,7 +662,8 @@ define(
           enableCellNavigation: true,
           enableColumnReorder: false,
           asyncEditorLoading: false,
-          autoEdit: false
+          autoEdit: false,
+          dataItemColumnValueExtractor: this.get_item_column_value
         };
 
         var $data_grid = self.$el.find('#datagrid');
@@ -705,11 +716,26 @@ define(
         if (editor_data.selection) {
            editor_data.selection.onSelectedRangesChanged.subscribe(function(e, args) {
              var collection = this.grid.getData(),
-               _pk = _.keys(this.keys),
+               primary_key_list = _.keys(this.keys),
+               _tmp_keys = [],
+               _columns = this.columns,
                rows_for_stage = {}, selected_rows_list = [];
+
                // Only if entire row(s) are selected via check box
                if(_.has(this.selection, 'getSelectedRows')) {
                  selected_rows_list = this.selection.getSelectedRows();
+                 // We will map selected row primary key name with position
+                 // For each Primary key
+                 _.each(primary_key_list, function(p) {
+                   // For each columns search primary key position
+                   _.each(_columns, function(c) {
+                      if(c.name == p) {
+                        _tmp_keys.push(c.pos);
+                      }
+                   });
+                 });
+                 // Now assign mapped temp PK to PK
+                 primary_key_list =  _tmp_keys;
                }
 
               // If any row(s) selected ?
@@ -717,12 +743,14 @@ define(
                 if(this.editor.handler.can_edit)
                   // Enable delete rows button
                   $("#btn-delete-row").prop('disabled', false);
+
                 // Enable copy rows button
                 $("#btn-copy-row").prop('disabled', false);
                 // Collect primary key data from collection as needed for stage row
                 _.each(selected_rows_list, function(row_index) {
-                  var row_data = collection[row_index], _selected = {};
-                  rows_for_stage[row_data.__temp_PK] = _.pick(row_data, _pk);
+                  var row_data = collection[row_index];
+                  // Store Primary key data for selected rows
+                  rows_for_stage[row_data.__temp_PK] = _.pick(row_data, primary_key_list);
                 });
               } else {
                 // Clear the object as no rows to delete
@@ -733,7 +761,7 @@ define(
               }
 
              // Update main data store
-            this.editor.handler.data_store.staged_rows = rows_for_stage;
+             this.editor.handler.data_store.staged_rows = rows_for_stage;
            }.bind(editor_data));
         }
 
@@ -742,7 +770,7 @@ define(
         // This will be used to collect primary key for that row
         grid.onBeforeEditCell.subscribe(function (e, args) {
             var before_data = args.item;
-            if(before_data && '__temp_PK' in before_data) {
+            if(self.handler.can_edit && before_data && '__temp_PK' in before_data) {
               var _pk = before_data.__temp_PK,
                 _keys = self.handler.primary_keys,
                 current_pk = {}, each_pk_key = {};
@@ -753,8 +781,10 @@ define(
               }
 
               // Fetch primary keys for the row before they gets modified
+              var _columns = self.handler.columns;
               _.each(_keys, function(value, key) {
-                current_pk[key] = before_data[key];
+                pos = _.where(_columns, {name: key})[0]['pos']
+                current_pk[pos] = before_data[pos];
               });
               // Place it in main variable for later use
               self.handler.primary_keys_data[_pk] = current_pk
@@ -787,8 +817,8 @@ define(
             // Fetch current row data from grid
             column_values = grid.getDataItem(row, cell)
             //  Get the value from cell
-            value = column_values[column_info.field] || '';
-            //Copy this value to Clipborad
+            value = column_values[column_info.pos] || '';
+            // Copy this value to Clipboard
             if(value)
               this.editor.handler.copyTextToClipboard(value);
             // Go to cell again
@@ -801,7 +831,7 @@ define(
         // Listener function which will be called when user updates existing rows
         grid.onCellChange.subscribe(function (e, args) {
           // self.handler.data_store.updated will holds all the updated data
-          var changed_column = args.grid.getColumns()[args.cell].field, // Current filed name
+          var changed_column = args.grid.getColumns()[args.cell].pos, // Current field pos
             updated_data = args.item[changed_column],                   // New value for current field
             _pk = args.item.__temp_PK || null,                          // Unique key to identify row
             column_data = {},
@@ -817,7 +847,7 @@ define(
                   column_data);
               //Find type for current column
               self.handler.data_store.added[_pk]['err'] = false
-              self.handler.data_store.added[_pk]['data_type'][changed_column] = _.where(this.columns, {name: changed_column})[0]['type'];
+              self.handler.data_store.added[_pk]['data_type'][changed_column] = _.where(this.columns, {pos: changed_column})[0]['type'];
             // Check if it is updated data from existing rows?
             } else if(_pk in self.handler.data_store.updated) {
               _.extend(
@@ -827,7 +857,7 @@ define(
               self.handler.data_store.updated[_pk]['err'] = false
 
              //Find type for current column
-             self.handler.data_store.updated[_pk]['data_type'][changed_column] = _.where(this.columns, {name: changed_column})[0]['type'];
+             self.handler.data_store.updated[_pk]['data_type'][changed_column] = _.where(this.columns, {pos: changed_column})[0]['type'];
             } else {
               // First updated data for this primary key
               self.handler.data_store.updated[_pk] = {
@@ -837,7 +867,7 @@ define(
               self.handler.data_store.updated_index[args.row] = _pk;
               // Find & add column data type for current changed column
               var temp = {};
-              temp[changed_column] = _.where(this.columns, {name: changed_column})[0]['type'];
+              temp[changed_column] = _.where(this.columns, {pos: changed_column})[0]['type'];
               self.handler.data_store.updated[_pk]['data_type'] = temp;
             }
           }
@@ -860,7 +890,7 @@ define(
           self.handler.data_store.added_index[data_length] = _key;
           // Fetch data type & add it for the column
           var temp = {};
-          temp[column.field] = _.where(this.columns, {name: column.field})[0]['type'];
+          temp[column.pos] = _.where(this.columns, {pos: column.pos})[0]['type'];
           self.handler.data_store.added[_key]['data_type'] =  temp;
           grid.invalidateRows([collection.length - 1]);
           grid.updateRowCount();
@@ -1666,6 +1696,7 @@ define(
           var self = this;
           self.query_start_time = new Date();
           self.rows_affected = 0;
+          self._init_polling_flags();
 
           self.trigger(
             'pgadmin-sqleditor:loading-icon:show',
@@ -1744,6 +1775,74 @@ define(
           });
         },
 
+        // This function makes the ajax call to fetch columns for last async query,
+        get_columns: function(poll_result) {
+          var self = this;
+          // Check the flag and decide if we need to fetch columns from server
+          // or use the columns data stored locally from previous call?
+          if (self.FETCH_COLUMNS_FROM_SERVER) {
+            $.ajax({
+              url: "{{ url_for('sqleditor.index') }}" + "columns/" + self.transId,
+              method: 'GET',
+              success: function(res) {
+                poll_result.colinfo = res.data.columns;
+                poll_result.primary_keys = res.data.primary_keys;
+                self.call_render_after_poll(poll_result);
+                // Set a flag to get columns to false & set the value for future use
+                self.FETCH_COLUMNS_FROM_SERVER = false;
+                self.COLUMNS_DATA = res;
+              },
+              error: function(e) {
+                var msg = e.responseText;
+                if (e.responseJSON != undefined && e.responseJSON.errormsg != undefined)
+                  msg = e.responseJSON.errormsg;
+                  alertify.error(msg, 5);
+              }
+            });
+          } else {
+            // Use the previously saved columns data
+            poll_result.colinfo = self.COLUMNS_DATA.data.columns;
+            poll_result.primary_keys = self.COLUMNS_DATA.data.primary_keys;
+            self.call_render_after_poll(poll_result);
+          }
+        },
+
+        // This is a wrapper to call _render function
+        // We need this because we have separated columns route & result route
+        // We need to combine both result here in wrapper before rendering grid
+        call_render_after_poll: function(res) {
+          var self = this;
+          self.query_end_time = new Date();
+          self.rows_affected = res.rows_affected;
+
+          /* If no column information is available it means query
+             runs successfully with no result to display. In this
+             case no need to call render function.
+          */
+          if (res.colinfo != null)
+            self._render(res);
+          else {
+            // Show message in message and history tab in case of query tool
+            self.total_time = self.get_query_run_time(self.query_start_time, self.query_end_time);
+            var msg = S('{{ _('Query returned successfully in %s.') }}').sprintf(self.total_time).value();
+            res.result += "\n\n" + msg;
+            self.update_msg_history(true, res.result, false);
+            // Display the notifier if the timeout is set to >= 0
+            if (self.info_notifier_timeout >= 0) {
+              alertify.success(msg, self.info_notifier_timeout);
+            }
+          }
+
+          // Enable/Disable query tool button only if is_query_tool is true.
+          if (self.is_query_tool) {
+            self.disable_tool_buttons(false);
+            $("#btn-cancel-query").prop('disabled', true);
+          }
+          is_query_running = false;
+          self.trigger('pgadmin-sqleditor:loading-icon:hide');
+        },
+
+
         /* This function makes the ajax call to poll the result,
          * if status is Busy then recursively call the poll function
          * till the status is 'Success' or 'NotConnected'. If status is
@@ -1751,6 +1850,7 @@ define(
          */
         _poll: function() {
           var self = this;
+
           setTimeout(
             function() {
               $.ajax({
@@ -1762,35 +1862,7 @@ define(
                       'pgadmin-sqleditor:loading-icon:message',
                       '{{ _('Loading data from the database server and rendering...') }}'
                     );
-
-                    self.query_end_time = new Date();
-                    self.rows_affected = res.data.rows_affected;
-
-                    /* If no column information is available it means query
-                       runs successfully with no result to display. In this
-                       case no need to call render function.
-                     */
-                    if (res.data.colinfo != null)
-                      self._render(res.data);
-                    else {
-                      // Show message in message and history tab in case of query tool
-                      self.total_time = self.get_query_run_time(self.query_start_time, self.query_end_time);
-                      var msg = S('{{ _('Query returned successfully in %s.') }}').sprintf(self.total_time).value();
-                      res.data.result += "\n\n" + msg;
-                      self.update_msg_history(true, res.data.result, false);
-                      // Display the notifier if the timeout is set to >= 0
-                      if (self.info_notifier_timeout >= 0) {
-                          alertify.success(msg, self.info_notifier_timeout);
-                      }
-                    }
-
-                    // Enable/Disable query tool button only if is_query_tool is true.
-                    if (self.is_query_tool) {
-                      self.disable_tool_buttons(false);
-                      $("#btn-cancel-query").prop('disabled', true);
-                    }
-                    is_query_running = false;
-                    self.trigger('pgadmin-sqleditor:loading-icon:hide');
+                    self.get_columns(res.data);
                   }
                   else if (res.data.status === 'Busy') {
                     // If status is Busy then poll the result by recursive call to the poll function
@@ -1837,7 +1909,7 @@ define(
                   self.update_msg_history(false, msg);
                 }
               });
-          }, 1);
+          }, self.POLL_FALLBACK_TIME());
         },
 
         /* This function is used to create the backgrid columns,
@@ -1922,13 +1994,13 @@ define(
                * and add json formatted data to collection and render.
                */
               var explain_data_array = [];
-              if(
+              if (
                 data.result && data.result.length >= 1 &&
-                  data.result[0] && data.result[0].hasOwnProperty(
-                    'QUERY PLAN'
-                  ) && _.isObject(data.result[0]['QUERY PLAN'])
+                data.result[0] && data.result[0][0] && data.result[0][0][0] &&
+                data.result[0][0][0].hasOwnProperty('Plan') &&
+                _.isObject(data.result[0][0][0]['Plan'])
               ) {
-                var explain_data = {'QUERY PLAN' : JSON.stringify(data.result[0]['QUERY PLAN'], null, 2)};
+                var explain_data = [JSON.stringify(data.result[0][0], null, 2)];
                 explain_data_array.push(explain_data);
                 // Make sure - the 'Data Output' panel is visible, before - we
                 // start rendering the grid.
@@ -1942,7 +2014,7 @@ define(
                     // start rendering the grid.
                     self.gridView.explain_panel.focus();
                     pgExplain.DrawJSONPlan(
-                      $('.sql-editor-explain'), data.result[0]['QUERY PLAN']
+                      $('.sql-editor-explain'), data.result[0][0]
                     );
                   }, 10
                 );
@@ -2067,6 +2139,7 @@ define(
 
                   var col = {
                     'name': c.name,
+                    'pos': c.pos,
                     'label': column_label,
                     'cell': col_cell,
                     'can_edit': self.can_edit,
@@ -2278,12 +2351,16 @@ define(
               '{{ _('Saving the updated data...') }}'
             );
 
+            // Add the columns to the data so the server can remap the data
+            req_data = self.data_store
+            req_data.columns = view ? view.handler.columns : self.columns;
+
             // Make ajax call to save the data
             $.ajax({
               url: "{{ url_for('sqleditor.index') }}" + "save/" + self.transId,
               method: 'POST',
               contentType: "application/json",
-              data: JSON.stringify(self.data_store),
+              data: JSON.stringify(req_data),
               success: function(res) {
                 var grid = self.slickgrid,
                   data = grid.getData();
@@ -2592,6 +2669,37 @@ define(
           }
         },
 
+        // This function will set the required flag for polling response data
+        _init_polling_flags: function() {
+          var self = this;
+          // Set a flag to get columns
+          self.FETCH_COLUMNS_FROM_SERVER = true;
+          // We will set columns data in this variable for future use once we fetch it
+          // from server
+          self.COLUMNS_DATA = {};
+
+          // To get a timeout for polling fallback timer in seconds in
+          // regards to elapsed time
+          self.POLL_FALLBACK_TIME = function() {
+            var seconds = parseInt((Date.now() - self.query_start_time.getTime())/1000);
+            // calculate & return fall back polling timeout
+            if(seconds >= 10 && seconds < 30) {
+              return 500;
+            }
+            else if(seconds >= 30 && seconds < 60) {
+              return 1000;
+            }
+            else if(seconds >= 60 && seconds < 90) {
+              return 2000;
+            }
+            else if(seconds >= 90) {
+              return 5000;
+            }
+            else
+              return 1;
+          }
+        },
+
         // This function will show the filter in the text area.
         _show_filter: function() {
           var self = this;
@@ -2663,8 +2771,8 @@ define(
           if (_.isNull(_values) || _.isUndefined(_values))
             return;
 
-          // Add column name and it's' value to data
-          data[column_info.field] = _values[column_info.field] || '';
+          // Add column position and it's value to data
+          data[column_info.pos] = _values[column_info.pos] || '';
 
           self.trigger(
             'pgadmin-sqleditor:loading-icon:show',
@@ -2733,8 +2841,8 @@ define(
           if (_.isNull(_values) || _.isUndefined(_values))
             return;
 
-          // Add column name and it's' value to data
-          data[column_info.field] = _values[column_info.field] || '';
+          // Add column position and it's value to data
+          data[column_info.pos] = _values[column_info.pos] || '';
 
           self.trigger(
             'pgadmin-sqleditor:loading-icon:show',
@@ -2971,10 +3079,10 @@ define(
             self.copied_rows.push(_rowData);
             // Convert it as CSV for clipboard
             for (var j = 0; j < self.columns.length; j += 1) {
-               var val = _rowData[self.columns[j].name];
+               var val = _rowData[self.columns[j].pos];
                if(val && _.isObject(val))
                  val = "'" + JSON.stringify(val) + "'";
-               else if(val && typeof val != "number")
+               else if(val && typeof val != "number" && typeof true != "boolean")
                  val = "'" + val.toString() + "'";
                else if (_.isNull(val) || _.isUndefined(val))
                  val = '';
@@ -2995,7 +3103,8 @@ define(
             grid = self.slickgrid,
             data = grid.getData();
             // Deep copy
-            var copied_rows = $.extend(true, [], self.copied_rows);
+            var copied_rows = $.extend(true, [], self.copied_rows),
+            _tmp_copied_row = {};
 
             // If there are rows to paste?
             if(copied_rows.length > 0) {
@@ -3016,7 +3125,7 @@ define(
 
               // Fetch column name & its data type
               _.each(self.columns, function(c) {
-                col_info[c.name] = c.type;
+                col_info[String(c.pos)] = c.type;
               });
 
               // insert these data in data_store as well to save them on server
@@ -3026,16 +3135,22 @@ define(
                   'data': {}
                 };
                 self.data_store.added[copied_rows[j].__temp_PK]['data_type'] = col_info;
+                // We need to convert it from array to dict so that server can
+                // understand the data properly
                 _.each(copied_rows[j], function(val, key) {
                   // If value is array then convert it to string
                   if(_.isArray(val)) {
-                    copied_rows[j][key] = val.toString();
+                    _tmp_copied_row[String(key)] = val.toString();
                   // If value is object then stringify it
                   } else if(_.isObject(val)) {
-                    copied_rows[j][key] = JSON.stringify(val);
+                    _tmp_copied_row[j][String(key)] = JSON.stringify(val);
+                  } else {
+                    _tmp_copied_row[String(key)] = val;
                   }
                 });
-                self.data_store.added[copied_rows[j].__temp_PK]['data'] = copied_rows[j];
+                self.data_store.added[copied_rows[j].__temp_PK]['data'] = _tmp_copied_row;
+                // reset the variable
+                _tmp_copied_row = {};
               }
             }
         },
@@ -3132,7 +3247,7 @@ define(
           self.query_start_time = new Date();
           self.query = sql;
           self.rows_affected = 0;
-
+          self._init_polling_flags();
           self.disable_tool_buttons(true);
           $("#btn-cancel-query").prop('disabled', false);
 
diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py b/web/pgadmin/utils/driver/psycopg2/__init__.py
index d63a0e1..b1b3147 100644
--- a/web/pgadmin/utils/driver/psycopg2/__init__.py
+++ b/web/pgadmin/utils/driver/psycopg2/__init__.py
@@ -42,8 +42,6 @@ else:
 
 _ = gettext
 
-ASYNC_WAIT_TIMEOUT = 0.01  # in seconds or 10 milliseconds
-
 # This registers a unicode type caster for datatype 'RECORD'.
 psycopg2.extensions.register_type(
     psycopg2.extensions.new_type((2249,), "RECORD",
@@ -696,7 +694,7 @@ WHERE
             self.__notices = []
             self.execution_aborted = False
             cur.execute(query, params)
-            res = self._wait_timeout(cur.connection, ASYNC_WAIT_TIMEOUT)
+            res = self._wait_timeout(cur.connection)
         except psycopg2.Error as pe:
             errmsg = self._formatted_exception_msg(pe, formatted_exception_msg)
             current_app.logger.error(u"""
@@ -1003,7 +1001,7 @@ Failed to reset the connection to the server due to following error:
             else:
                 raise psycopg2.OperationalError("poll() returned %s from _wait function" % state)
 
-    def _wait_timeout(self, conn, time):
+    def _wait_timeout(self, conn):
         """
         This function is used for the asynchronous connection,
         it will call poll method and return the status. If state is
@@ -1021,7 +1019,7 @@ Failed to reset the connection to the server due to following error:
         elif state == psycopg2.extensions.POLL_WRITE:
             # Wait for the given time and then check the return status
             # If three empty lists are returned then the time-out is reached.
-            timeout_status = select.select([], [conn.fileno()], [], time)
+            timeout_status = select.select([], [conn.fileno()], [], 0)
             if timeout_status == ([], [], []):
                 return self.ASYNC_WRITE_TIMEOUT
 
@@ -1034,10 +1032,27 @@ Failed to reset the connection to the server due to following error:
         elif state == psycopg2.extensions.POLL_READ:
             # Wait for the given time and then check the return status
             # If three empty lists are returned then the time-out is reached.
-            timeout_status = select.select([conn.fileno()], [], [], time)
+            timeout_status = select.select([conn.fileno()], [], [], 0)
             if timeout_status == ([], [], []):
                 return self.ASYNC_READ_TIMEOUT
 
+            # select.select timeout option works only if we provide
+            #  empty [] [] [] file descriptor in select.select() function
+            # and that also works only on UNIX based system, it do not support Windows
+            # Hence we have wrote our own pooling mechanism to to read data fast
+            # each call conn.poll() reads chunks of data from connection object
+            # more we poll more we read data from connection
+            cnt = 0
+            while cnt < 1000:
+                # poll again to check the state if it is still POLL_READ
+                # then return ASYNC_READ_TIMEOUT else return ASYNC_OK.
+                state = conn.poll()
+                if state == psycopg2.extensions.POLL_OK:
+                    return self.ASYNC_OK
+                cnt += 1
+            return self.ASYNC_READ_TIMEOUT
+
+
             # poll again to check the state if it is still POLL_READ
             # then return ASYNC_READ_TIMEOUT else return ASYNC_OK.
             state = conn.poll()
@@ -1075,42 +1090,48 @@ Failed to reset the connection to the server due to following error:
         )
 
         try:
-            status = self._wait_timeout(self.conn, ASYNC_WAIT_TIMEOUT)
+            status = self._wait_timeout(self.conn)
         except psycopg2.Error as pe:
-            if cur.closed:
+            if self.conn.closed:
                 raise ConnectionLost(
                     self.manager.sid,
                     self.db,
                     self.conn_id[5:]
                 )
             errmsg = self._formatted_exception_msg(pe, formatted_exception_msg)
-            return False, errmsg, None
+            return False, errmsg
 
         if self.conn.notices and self.__notices is not None:
             while self.conn.notices:
                 self.__notices.append(self.conn.notices.pop(0)[:])
 
-        colinfo = None
         result = None
         self.row_count = 0
+        self.column_info = None
+
         if status == self.ASYNC_OK:
 
             # if user has cancelled the transaction then changed the status
             if self.execution_aborted:
                 status = self.ASYNC_EXECUTION_ABORTED
                 self.execution_aborted = False
-                return status, result, colinfo
+                return status, result
 
             # Fetch the column information
             if cur.description is not None:
-                colinfo = [
+                self.column_info = [
                     desc.to_dict() for desc in cur.ordered_description()
                 ]
 
+                pos = 0
+                for col in self.column_info:
+                    col['pos'] = pos
+                    pos = pos + 1
+
             self.row_count = cur.rowcount
+
             if cur.rowcount > 0:
                 result = []
-
                 # For DDL operation, we may not have result.
                 #
                 # Because - there is not direct way to differentiate DML and
@@ -1118,10 +1139,15 @@ Failed to reset the connection to the server due to following error:
                 # out at the moment.
                 try:
                     for row in cur:
-                        result.append(dict(row))
+                        new_row = []
+                        for col in self.column_info:
+                            new_row.append(row[col['name']])
+                        result.append(new_row)
+
                 except psycopg2.ProgrammingError:
                     result = None
-        return status, result, colinfo
+
+        return status, result
 
     def status_message(self):
         """
@@ -1148,6 +1174,14 @@ Failed to reset the connection to the server due to following error:
 
         return self.row_count
 
+    def get_column_info(self):
+        """
+        This function will returns list of columns for last async sql command
+        executed on the server.
+        """
+
+        return self.column_info
+
     def cancel_transaction(self, conn_id, did=None):
         """
         This function is used to cancel the running transaction
