From 97919d091a64afcd3f168c4ebaad04fce442b8a7 Mon Sep 17 00:00:00 2001
From: Khushboo Vashi <khushboo.vashi@enterprisedb.com>
Date: Thu, 28 Mar 2019 13:13:43 -0400
Subject: [PATCH] Add support for IDENTITY columns. Fixes #4030

---
 docs/en_US/release_notes_4_4.rst              |   1 +
 .../databases/schemas/sequences/__init__.py   |  23 ++-
 .../tables/columns/static/js/column.js        | 133 +++++++++++-
 .../tables/columns/tests/test_column_add.py   |  42 +++-
 .../tables/columns/tests/test_column_put.py   |  46 ++++-
 .../schemas/tables/static/js/table.js         |  18 +-
 .../templates/column/sql/10_plus/create.sql   |  46 +++++
 .../column/sql/10_plus/properties.sql         |  46 +++++
 .../templates/column/sql/10_plus/update.sql   | 192 ++++++++++++++++++
 .../column/sql/default/properties.sql         |   2 +-
 .../templates/table/sql/10_plus/create.sql    | 168 +++++++++++++++
 .../sql/10_plus/get_columns_for_table.sql     |  16 ++
 web/pgadmin/browser/utils.py                  |  10 +-
 web/pgadmin/static/js/backform.pgadmin.js     |   1 +
 .../static/scss/_backgrid.overrides.scss      |   4 +
 15 files changed, 723 insertions(+), 25 deletions(-)
 create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/create.sql
 create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/properties.sql
 create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/update.sql
 create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/create.sql
 create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/get_columns_for_table.sql

#diff --git a/docs/en_US/release_notes_4_4.rst b/docs/en_US/release_notes_4_4.rst
#index 463bc3360e..0a6ac1cccc 100644
#--- a/docs/en_US/release_notes_4_4.rst
#+++ b/docs/en_US/release_notes_4_4.rst
#@@ -32,6 +32,7 @@ Features
# | `Feature #2001 <https://redmine.postgresql.org/issues/2001>`_ - Add support for reverse proxied setups with Gunicorn, and document Gunicorn, uWSGI & NGINX configurations.
# | `Feature #4017 <https://redmine.postgresql.org/issues/4018>`_ - Make the Query Tool history persistent across sessions.
# | `Feature #4018 <https://redmine.postgresql.org/issues/4018>`_ - Remove the large and unnecessary dependency on React and 87 other related libraries.
#+| `Feature #4030 <https://redmine.postgresql.org/issues/4030>`_ - Add support for IDENTITY columns.
# | `Feature #4075 <https://redmine.postgresql.org/issues/4075>`_ - Add an ePub doc build target.
# 
# Bug fixes
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py
index 56b2a676e9..f580ede0e4 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py
@@ -228,6 +228,14 @@ def nodes(self, gid, sid, did, scid, seid=None):
             )
 
         for row in rset['rows']:
+            if not self.blueprint.show_system_objects:
+                system_seq = self._get_dependency(row['oid'], show_system_objects=True)
+                seq = filter(lambda dep: dep['type'] == 'column', system_seq)
+                if type(seq) is not list:
+                    seq = list(seq)
+                if len(seq) > 0:
+                    continue
+
             res.append(
                 self.blueprint.generate_browser_node(
                     row['oid'],
@@ -760,7 +768,14 @@ def dependencies(self, gid, sid, did, scid, seid):
             scid: Schema ID
             seid: Sequence ID
         """
-        dependencies_result = self.get_dependencies(self.conn, seid)
+
+        return ajax_response(
+            response=self._get_dependency(seid),
+            status=200
+        )
+
+    def _get_dependency(self, seid, show_system_objects=None):
+        dependencies_result = self.get_dependencies(self.conn, seid, None, show_system_objects)
 
         # Get missing dependencies.
         # A Corner case, reported by Guillaume Lelarge, could be found at:
@@ -790,11 +805,7 @@ def dependencies(self, gid, sid, did, scid, seid):
             dependencies_result.append({'type': 'column',
                                         'name': ref_name,
                                         'field': dep_type})
-
-        return ajax_response(
-            response=dependencies_result,
-            status=200
-        )
+        return dependencies_result
 
     @check_precondition(action="stats")
     def statistics(self, gid, sid, did, scid, seid=None):
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js
index c4f1918462..64ce448112 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js
@@ -185,6 +185,13 @@ define('pgadmin.node.column', [
           attnotnull: false,
           attlen: null,
           attprecision: null,
+          attidentity: undefined,
+          seqincrement: undefined,
+          seqstart: undefined,
+          seqmin: undefined,
+          seqmax: undefined,
+          seqcache: undefined,
+          seqcycle: undefined,
         },
         schema: [{
           id: 'name', label: gettext('Name'), cell: 'string',
@@ -258,8 +265,7 @@ define('pgadmin.node.column', [
               return false;
             }
 
-            if(!m.inSchemaWithColumnCheck.apply(this, [m]) &&
-              !_.isUndefined(name) && !_.isNull(name) && name !== '') {
+            if(!m.inSchemaWithColumnCheck.apply(this, [m])) {
               return true;
             }
             return false;
@@ -478,6 +484,52 @@ define('pgadmin.node.column', [
           type: 'switch', disabled: 'inSchemaWithColumnCheck', cellHeaderClasses:'width_percent_20',
           group: gettext('Definition'), editable: 'editable_check_for_table',
           options: { onText: gettext('Yes'), offText: gettext('No'), onColor: 'success', offColor: 'primary' },
+        },{
+          type: 'nested', control: 'fieldset', label: gettext('Identity'),
+          group: gettext('Definition'),
+          schema:[{
+            id: 'attidentity', label: gettext('Identity'), control: 'select2',
+            cell: 'select2', select2: { placeholder: 'Select identity',
+              allowClear: true,
+              width: '100%',
+            },
+            min_version: 100000, group: gettext('Identity'),
+            'options': [
+              {label: gettext('ALWAYS'), value: 'a'},
+              {label: gettext('BY DEFAULT'), value: 'd'},
+            ],
+          },{
+            id: 'seqincrement', label: gettext('Increment'), type: 'int',
+            mode: ['properties', 'create', 'edit'], group: gettext('Identity'),
+            min: 1, deps: ['attidentity'], disabled: 'isIdentityColumn',
+          },{
+            id: 'seqstart', label: gettext('Start'), type: 'int',
+            mode: ['properties', 'create'], group: gettext('Identity'),
+            disabled: function(m) {
+              if (!m.isNew())
+                return true;
+              let isIdentity = m.get('attidentity');
+              if(!_.isUndefined(isIdentity) && !_.isNull(isIdentity) && !_.isEmpty(isIdentity))
+                return false;
+              return true;
+            }, deps: ['attidentity'],
+          },{
+            id: 'seqmin', label: gettext('Minimum'), type: 'int',
+            mode: ['properties', 'create', 'edit'], group: gettext('Identity'),
+            deps: ['attidentity'], disabled: 'isIdentityColumn',
+          },{
+            id: 'seqmax', label: gettext('Maximum'), type: 'int',
+            mode: ['properties', 'create', 'edit'], group: gettext('Identity'),
+            deps: ['attidentity'], disabled: 'isIdentityColumn',
+          },{
+            id: 'seqcache', label: gettext('Cache'), type: 'int',
+            mode: ['properties', 'create', 'edit'], group: gettext('Identity'),
+            min: 1, deps: ['attidentity'], disabled: 'isIdentityColumn',
+          },{
+            id: 'seqcycle', label: gettext('Cycled'), type: 'switch',
+            mode: ['properties', 'create', 'edit'], group: gettext('Identity'),
+            deps: ['attidentity'], disabled: 'isIdentityColumn',
+          }],
         },{
           id: 'attstattarget', label: gettext('Statistics'), cell: 'string',
           type: 'text', disabled: 'inSchemaWithColumnCheck', mode: ['properties', 'edit'],
@@ -603,8 +655,85 @@ define('pgadmin.node.column', [
             }
           }
 
+          var  minimum = this.get('seqmin'),
+            maximum = this.get('seqmax'),
+            start = this.get('seqstart');
+
+          if (!this.isNew()) {
+            if (_.isUndefined(this.get('seqincrement'))
+              || String(this.get('seqincrement')).replace(/^\s+|\s+$/g, '') == '') {
+              msg = gettext('Increment value cannot be empty.');
+              this.errorModel.set('seqincrement', msg);
+              return msg;
+            } else {
+              this.errorModel.unset('seqincrement');
+            }
+
+            if (_.isUndefined(this.get('seqmin'))
+              || String(this.get('seqmin')).replace(/^\s+|\s+$/g, '') == '') {
+              msg = gettext('Minimum value cannot be empty.');
+              this.errorModel.set('seqmin', msg);
+              return msg;
+            } else {
+              this.errorModel.unset('seqmin');
+            }
+
+            if (_.isUndefined(this.get('seqmax'))
+              || String(this.get('seqmax')).replace(/^\s+|\s+$/g, '') == '') {
+              msg = gettext('Maximum value cannot be empty.');
+              this.errorModel.set('seqmax', msg);
+              return msg;
+            } else {
+              this.errorModel.unset('seqmax');
+            }
+
+            if (_.isUndefined(this.get('seqcache'))
+              || String(this.get('seqcache')).replace(/^\s+|\s+$/g, '') == '') {
+              msg = gettext('Cache value cannot be empty.');
+              this.errorModel.set('seqcache', msg);
+              return msg;
+            } else {
+              this.errorModel.unset('seqcache');
+            }
+          }
+          var min_lt = gettext('Minimum value must be less than maximum value.'),
+            start_lt = gettext('Start value cannot be less than minimum value.'),
+            start_gt = gettext('Start value cannot be greater than maximum value.');
+
+          if (_.isEmpty(minimum) || _.isEmpty(maximum))
+            return null;
+
+          if ((minimum == 0 && maximum == 0) ||
+              (parseInt(minimum, 10) >= parseInt(maximum, 10))) {
+            this.errorModel.set('seqmin', min_lt);
+            return min_lt;
+          } else {
+            this.errorModel.unset('seqmin');
+          }
+
+          if (start && minimum && parseInt(start) < parseInt(minimum)) {
+            this.errorModel.set('seqstart', start_lt);
+            return start_lt;
+          } else {
+            this.errorModel.unset('seqstart');
+          }
+
+          if (start && maximum && parseInt(start) > parseInt(maximum)) {
+            this.errorModel.set('seqstart', start_gt);
+            return start_gt;
+          } else {
+            this.errorModel.unset('seqstart');
+          }
+
           return null;
         },
+        // Check whether the column is identity column or not
+        isIdentityColumn: function(m) {
+          let isIdentity = m.get('attidentity');
+          if(!_.isUndefined(isIdentity) && !_.isNull(isIdentity) && !_.isEmpty(isIdentity))
+            return false;
+          return true;
+        },
         // We will check if we are under schema node & in 'create' mode
         notInSchema: function() {
           if(this.node_info &&  'catalog' in this.node_info)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/tests/test_column_add.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/tests/test_column_add.py
index d55f8c919c..0ced9cfd70 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/tests/test_column_add.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/tests/test_column_add.py
@@ -19,12 +19,38 @@
 from pgadmin.utils.route import BaseTestGenerator
 from regression import parent_node_dict
 from regression.python_test_utils import test_utils as utils
+from pgadmin.utils import server_utils as server_utils
+
 
 
 class ColumnAddTestCase(BaseTestGenerator):
     """This class will add new column under table node."""
     scenarios = [
-        ('Add column Node URL', dict(url='/browser/column/obj/'))
+        ('Add column', dict(url='/browser/column/obj/')),
+        ('Add column with Identity', dict(url='/browser/column/obj/',
+                                          server_min_version=100000,
+                                          identity_opt={
+                                              'cltype': 'bigint',
+                                              'attidentity': 'a',
+                                              'seqincrement': 1,
+                                              'seqstart': 1,
+                                              'seqmin': 1,
+                                              'seqmax': 10,
+                                              'seqcache': 1,
+                                              'seqcycle': True
+                                          })),
+        ('Add column with Identity', dict(url='/browser/column/obj/',
+                                          server_min_version=100000,
+                                          identity_opt={
+                                              'cltype': 'bigint',
+                                              'attidentity': 'd',
+                                              'seqincrement': 2,
+                                              'seqstart': 2,
+                                              'seqmin': 2,
+                                              'seqmax': 2000,
+                                              'seqcache': 1,
+                                              'seqcycle': True
+                                          }))
     ]
 
     def setUp(self):
@@ -32,6 +58,17 @@ def setUp(self):
         schema_info = parent_node_dict["schema"][-1]
         self.server_id = schema_info["server_id"]
         self.db_id = schema_info["db_id"]
+
+        if hasattr(self, 'server_min_version'):
+            server_con = server_utils.connect_server(self, self.server_id)
+            if not server_con["info"] == "Server connected.":
+                raise Exception("Could not connect to server to add "
+                                "a table.")
+            if server_con["data"]["version"] < self.server_min_version:
+                message = "Identity columns are not supported by " \
+                          "PPAS/PG 10.0 and below."
+                self.skipTest(message)
+
         db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
                                                  self.server_id, self.db_id)
         if not db_con['data']["connected"]:
@@ -62,6 +99,9 @@ def runTest(self):
             "attoptions": [],
             "seclabels": []
         }
+
+        if hasattr(self, 'identity_opt'):
+            data.update(self.identity_opt)
         # Add table
         response = self.tester.post(
             self.url + str(utils.SERVER_GROUP) + '/' +
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/tests/test_column_put.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/tests/test_column_put.py
index 373f3740c4..d6653be17b 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/tests/test_column_put.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/tests/test_column_put.py
@@ -20,12 +20,39 @@
 from regression import parent_node_dict
 from regression.python_test_utils import test_utils as utils
 from . import utils as columns_utils
+from pgadmin.utils import server_utils as server_utils
+
 
 
 class ColumnPutTestCase(BaseTestGenerator):
     """This class will update the column under table node."""
     scenarios = [
-        ('Put column Node URL', dict(url='/browser/column/obj/'))
+        ('Edit column Node URL', dict(url='/browser/column/obj/',
+                                      col_data_type='char')),
+        ('Edit column with Identity', dict(url='/browser/column/obj/',
+                                           col_data_type='bigint',
+                                           server_min_version=100000,
+                                           identity_opt={
+                                              'attidentity': 'a',
+                                              'seqincrement': 1,
+                                              'seqstart': 1,
+                                              'seqmin': 1,
+                                              'seqmax': 10,
+                                              'seqcache': 1,
+                                              'seqcycle': True
+                                           })),
+        ('EDit column with Identity', dict(url='/browser/column/obj/',
+                                           server_min_version=100000,
+                                           col_data_type='bigint',
+                                           identity_opt={
+                                              'attidentity': 'd',
+                                              'seqincrement': 2,
+                                              'seqstart': 2,
+                                              'seqmin': 2,
+                                              'seqmax': 2000,
+                                              'seqcache': 1,
+                                              'seqcycle': True
+                                           }))
     ]
 
     def setUp(self):
@@ -33,6 +60,17 @@ def setUp(self):
         schema_info = parent_node_dict["schema"][-1]
         self.server_id = schema_info["server_id"]
         self.db_id = schema_info["db_id"]
+
+        if hasattr(self, 'server_min_version'):
+            server_con = server_utils.connect_server(self, self.server_id)
+            if not server_con["info"] == "Server connected.":
+                raise Exception("Could not connect to server to add "
+                                "a table.")
+            if server_con["data"]["version"] < self.server_min_version:
+                message = "Identity columns are not supported by " \
+                          "PPAS/PG 10.0 and below."
+                self.skipTest(message)
+
         db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
                                                  self.server_id, self.db_id)
         if not db_con['data']["connected"]:
@@ -53,7 +91,8 @@ def setUp(self):
                                                      self.db_name,
                                                      self.schema_name,
                                                      self.table_name,
-                                                     self.column_name)
+                                                     self.column_name,
+                                                     self.col_data_type)
 
     def runTest(self):
         """This function will update the column under table node."""
@@ -64,8 +103,11 @@ def runTest(self):
         data = {
             "attnum": self.column_id,
             "name": self.column_name,
+            "attnotnull": True,
             "description": "This is test comment for column"
         }
+        if hasattr(self, 'identity_opt'):
+            data.update(self.identity_opt)
         response = self.tester.put(
             self.url + str(utils.SERVER_GROUP) + '/' +
             str(self.server_id) + '/' +
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js
index 6653edd4b1..a76a4facb1 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js
@@ -716,7 +716,7 @@ define('pgadmin.node.table', [
         },{
           id: 'typname', label: gettext('Of type'), type: 'text',
           mode: ['properties', 'create', 'edit'],
-          disabled: 'checkOfType', url: 'get_oftype', group: 'advanced',
+          disabled: 'checkOfType', url: 'get_oftype', group: gettext('advanced'),
           deps: ['coll_inherits'], transform: function(data, cell) {
             var control = cell || this,
               m = control.model;
@@ -769,27 +769,27 @@ define('pgadmin.node.table', [
         },{
           id: 'fillfactor', label: gettext('Fill factor'), type: 'int',
           mode: ['create', 'edit'], min: 10, max: 100,
-          disabled: 'inSchema',group: 'advanced',
+          disabled: 'inSchema', group: gettext('advanced'),
         },{
           id: 'relhasoids', label: gettext('Has OIDs?'), cell: 'switch',
           type: 'switch', mode: ['properties', 'create', 'edit'],
-          disabled: 'inSchema', group: 'advanced',
+          disabled: 'inSchema', group: gettext('advanced'),
         },{
           id: 'relpersistence', label: gettext('Unlogged?'), cell: 'switch',
           type: 'switch', mode: ['properties', 'create', 'edit'],
           disabled: 'inSchemaWithModelCheck',
-          group: 'advanced',
+          group: gettext('advanced'),
         },{
           id: 'conname', label: gettext('Primary key'), cell: 'string',
-          type: 'text', mode: ['properties'], group: 'advanced',
+          type: 'text', mode: ['properties'], group: gettext('advanced'),
           disabled: 'inSchema',
         },{
           id: 'reltuples', label: gettext('Rows (estimated)'), cell: 'string',
-          type: 'text', mode: ['properties'], group: 'advanced',
+          type: 'text', mode: ['properties'], group: gettext('advanced'),
           disabled: 'inSchema',
         },{
           id: 'rows_cnt', label: gettext('Rows (counted)'), cell: 'string',
-          type: 'text', mode: ['properties'], group: 'advanced',
+          type: 'text', mode: ['properties'], group: gettext('advanced'),
           disabled: 'inSchema', control: Backform.InputControl.extend({
             formatter: {
               fromRaw: function (rawData) {
@@ -811,7 +811,7 @@ define('pgadmin.node.table', [
           }),
         },{
           id: 'relhassubclass', label: gettext('Inherits tables?'), cell: 'switch',
-          type: 'switch', mode: ['properties'], group: 'advanced',
+          type: 'switch', mode: ['properties'], group: gettext('advanced'),
           disabled: 'inSchema',
         },{
           id: 'is_sys_table', label: gettext('System table?'), cell: 'switch',
@@ -819,7 +819,7 @@ define('pgadmin.node.table', [
           disabled: 'inSchema',
         },{
           type: 'nested', control: 'fieldset', label: gettext('Like'),
-          group: 'advanced',
+          group: gettext('advanced'),
           schema:[{
             id: 'like_relation', label: gettext('Relation'),
             type: 'text', mode: ['create', 'edit'], deps: ['typname'],
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/create.sql
new file mode 100644
index 0000000000..67a7753fbe
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/create.sql
@@ -0,0 +1,46 @@
+{% import 'column/macros/security.macros' as SECLABEL %}
+{% import 'column/macros/privilege.macros' as PRIVILEGE %}
+{% import 'macros/variable.macros' as VARIABLE %}
+{% import 'type/macros/get_full_type_sql_format.macros' as GET_TYPE %}
+{###  Add column ###}
+{% if data.name and  data.cltype %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ADD COLUMN {{conn|qtIdent(data.name)}} {% if is_sql %}{{data.displaytypname}}{% else %}{{ GET_TYPE.CREATE_TYPE_SQL(conn, data.cltype, data.attlen, data.attprecision, data.hasSqrBracket) }}{% endif %}{% if data.collspcname %}
+ COLLATE {{data.collspcname}}{% endif %}{% if data.attnotnull %}
+ NOT NULL{% endif %}{% if data.defval and data.defval is not none %}
+ DEFAULT {{data.defval}}{% endif %}{% if data.attidentity and data.attidentity == 'a' %} GENERATED ALWAYS AS IDENTITY{% elif data.attidentity and data.attidentity == 'd' %} GENERATED BY DEFAULT AS IDENTITY{% endif %}
+ {% if data.seqincrement or data.seqcycle or data.seqincrement or data.seqstart or data.seqmin or data.seqmax or data.seqcache %} ( {% endif %}
+{% if data.seqincrement is defined and data.seqcycle %}
+CYCLE {% endif %}{% if data.seqincrement is defined and data.seqincrement|int(-1) > -1 %}
+INCREMENT {{data.seqincrement|int}} {% endif %}{% if data.seqstart is defined and data.seqstart|int(-1) > -1%}
+START {{data.seqstart|int}} {% endif %}{% if data.seqmin is defined and data.seqmin|int(-1) > -1%}
+MINVALUE {{data.seqmin|int}} {% endif %}{% if data.seqmax is defined and data.seqmax|int(-1) > -1%}
+MAXVALUE {{data.seqmax|int}} {% endif %}{% if data.seqcache is defined and data.seqcache|int(-1) > -1%}
+CACHE {{data.seqcache|int}} {% endif %}
+{% if data.seqincrement or data.seqcycle or data.seqincrement or data.seqstart or data.seqmin or data.seqmax or data.seqcache %}) {% endif %}
+{% endif %}
+
+{###  Add comments ###}
+{% if data and data.description %}
+COMMENT ON COLUMN {{conn|qtIdent(data.schema, data.table, data.name)}}
+    IS {{data.description|qtLiteral}};
+
+{% endif %}
+{###  Add variables to column ###}
+{% if data.attoptions %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    {{ VARIABLE.SET(conn, 'COLUMN', data.name, data.attoptions) }}
+
+{% endif %}
+{###  ACL ###}
+{% if data.attacl %}
+{% for priv in data.attacl %}
+{{ PRIVILEGE.APPLY(conn, data.schema, data.table, data.name, priv.grantee, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+{% endif %}
+{###  Security Lables ###}
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{{ SECLABEL.APPLY(conn, 'COLUMN',data.schema, data.table, data.name, r.provider, r.label) }}
+{% endfor %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/properties.sql
new file mode 100644
index 0000000000..186f5185ab
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/properties.sql
@@ -0,0 +1,46 @@
+SELECT att.attname as name, att.*, def.*, pg_catalog.pg_get_expr(def.adbin, def.adrelid) AS defval,
+        CASE WHEN att.attndims > 0 THEN 1 ELSE 0 END AS isarray,
+        format_type(ty.oid,NULL) AS typname,
+        format_type(ty.oid,att.atttypmod) AS displaytypname,
+        CASE WHEN ty.typelem > 0 THEN ty.typelem ELSE ty.oid END as elemoid,
+        tn.nspname as typnspname, et.typname as elemtypname,
+        ty.typstorage AS defaultstorage, cl.relname, na.nspname,
+        concat(quote_ident(na.nspname) ,'.', quote_ident(cl.relname)) AS parent_tbl,
+	att.attstattarget, description, cs.relname AS sername,
+	ns.nspname AS serschema,
+	(SELECT count(1) FROM pg_type t2 WHERE t2.typname=ty.typname) > 1 AS isdup,
+	indkey, coll.collname, nspc.nspname as collnspname , attoptions,
+	-- Start pgAdmin4, added to save time on client side parsing
+	CASE WHEN length(coll.collname) > 0 AND length(nspc.nspname) > 0  THEN
+	  concat(quote_ident(nspc.nspname),'.',quote_ident(coll.collname))
+	ELSE '' END AS collspcname,
+	format_type(ty.oid,att.atttypmod) AS cltype,
+	-- End pgAdmin4
+	EXISTS(SELECT 1 FROM pg_constraint WHERE conrelid=att.attrelid AND contype='f' AND att.attnum=ANY(conkey)) As is_fk,
+	(SELECT array_agg(provider || '=' || label) FROM pg_seclabels sl1 WHERE sl1.objoid=att.attrelid AND sl1.objsubid=att.attnum) AS seclabels,
+	(CASE WHEN (att.attnum < 1) THEN true ElSE false END) AS is_sys_column,
+	seq.*
+FROM pg_attribute att
+  JOIN pg_type ty ON ty.oid=atttypid
+  JOIN pg_namespace tn ON tn.oid=ty.typnamespace
+  JOIN pg_class cl ON cl.oid=att.attrelid
+  JOIN pg_namespace na ON na.oid=cl.relnamespace
+  LEFT OUTER JOIN pg_type et ON et.oid=ty.typelem
+  LEFT OUTER JOIN pg_attrdef def ON adrelid=att.attrelid AND adnum=att.attnum
+  LEFT OUTER JOIN pg_description des ON (des.objoid=att.attrelid AND des.objsubid=att.attnum AND des.classoid='pg_class'::regclass)
+  LEFT OUTER JOIN (pg_depend JOIN pg_class cs ON classid='pg_class'::regclass AND objid=cs.oid AND cs.relkind='S') ON refobjid=att.attrelid AND refobjsubid=att.attnum
+  LEFT OUTER JOIN pg_namespace ns ON ns.oid=cs.relnamespace
+  LEFT OUTER JOIN pg_index pi ON pi.indrelid=att.attrelid AND indisprimary
+  LEFT OUTER JOIN pg_collation coll ON att.attcollation=coll.oid
+  LEFT OUTER JOIN pg_namespace nspc ON coll.collnamespace=nspc.oid
+  LEFT OUTER JOIN pg_depend dep ON dep.refobjid = att.attrelid AND dep.refobjsubid = att.attnum AND dep.classid IN ( SELECT oid FROM pg_class WHERE relname IN ('pg_class')) LEFT JOIN pg_sequence seq ON dep.objid=seq.seqrelid
+WHERE att.attrelid = {{tid}}::oid
+{% if clid %}
+    AND att.attnum = {{clid}}::int
+{% endif %}
+{### To show system objects ###}
+{% if not show_sys_objects %}
+    AND att.attnum > 0
+{% endif %}
+    AND att.attisdropped IS FALSE
+    ORDER BY att.attnum;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/update.sql
new file mode 100644
index 0000000000..075647d8f7
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/10_plus/update.sql
@@ -0,0 +1,192 @@
+{% import 'column/macros/security.macros' as SECLABEL %}
+{% import 'column/macros/privilege.macros' as PRIVILEGE %}
+{% import 'macros/variable.macros' as VARIABLE %}
+{% import 'type/macros/get_full_type_sql_format.macros' as GET_TYPE %}
+{###  Rename column name ###}
+{% if data.name and data.name != o_data.name %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    RENAME {{conn|qtIdent(o_data.name)}} TO {{conn|qtIdent(data.name)}};
+
+{% endif %}
+{###  Alter column type and collation ###}
+{% if (data.cltype and data.cltype != o_data.cltype) or (data.attlen is defined and data.attlen is not none and data.attlen != o_data.attlen) or (data.attprecision is defined and data.attprecision != o_data.attprecision) or (data.collspcname and data.collspcname != o_data.collspcname)%}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} TYPE {{ GET_TYPE.UPDATE_TYPE_SQL(conn, data, o_data) }}{% if data.collspcname and data.collspcname != o_data.collspcname %}
+ COLLATE {{data.collspcname}}{% elif o_data.collspcname %} COLLATE {{o_data.collspcname}}{% endif %};
+{% endif %}
+{###  Alter column default value ###}
+{% if data.defval is defined and data.defval is not none and data.defval != '' and data.defval != o_data.defval %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} SET DEFAULT {{data.defval}};
+
+{% endif %}
+{###  Drop column default value ###}
+{% if data.defval is defined and data.defval == '' and data.defval != o_data.defval %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} DROP DEFAULT;
+
+{% endif %}
+{###  Alter column not null value ###}
+{% if 'attnotnull' in data and data.attnotnull != o_data.attnotnull %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} {% if data.attnotnull %}SET{% else %}DROP{% endif %} NOT NULL;
+
+{% endif %}
+{###  Alter column - add identity ###}
+{% if 'attidentity' in data and o_data.attidentity == '' and data.attidentity != o_data.attidentity %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} ADD GENERATED {% if data.attidentity == 'a' %}ALWAYS{% else%}BY DEFAULT{% endif %} AS IDENTITY
+    {% if data.seqincrement or data.seqcycle or data.seqincrement or data.seqstart or data.seqmin or data.seqmax or data.seqcache %} ( {% endif %}
+{% if data.seqincrement is defined and data.seqcycle %}
+CYCLE {% endif %}{% if data.seqincrement is defined and data.seqincrement|int(-1) > -1 %}
+INCREMENT {{data.seqincrement|int}} {% endif %}{% if data.seqstart is defined and data.seqstart|int(-1) > -1%}
+START {{data.seqstart|int}} {% endif %}{% if data.seqmin is defined and data.seqmin|int(-1) > -1%}
+MINVALUE {{data.seqmin|int}} {% endif %}{% if data.seqmax is defined and data.seqmax|int(-1) > -1%}
+MAXVALUE {{data.seqmax|int}} {% endif %}{% if data.seqcache is defined and data.seqcache|int(-1) > -1%}
+CACHE {{data.seqcache|int}} {% endif %}
+{% if data.seqincrement or data.seqcycle or data.seqincrement or data.seqstart or data.seqmin or data.seqmax or data.seqcache %}) {% endif %};
+{% endif %}
+{###  Alter column - change identity ###}
+{% if 'attidentity' in data and data.attidentity != '' and o_data.attidentity != '' and data.attidentity != o_data.attidentity %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} SET GENERATED {% if data.attidentity == 'a' %}ALWAYS{% else%}BY DEFAULT{% endif %};
+
+{% endif %}
+
+{###  Alter column - change identity - sequence options ###}
+{% if 'attidentity' not in data and (data.seqincrement or data.seqcycle or data.seqincrement or data.seqstart or data.seqmin or data.seqmax or data.seqcache) %}
+
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}} {% else %}{{conn|qtTypeIdent(o_data.name)}} {% endif %}
+{% if data.seqcycle %}
+SET CYCLE {% endif %}{% if data.seqincrement is defined and data.seqincrement|int(-1) > -1 %}
+SET INCREMENT {{data.seqincrement|int}} {% endif %}{% if data.seqstart is defined and data.seqstart|int(-1) > -1%}
+SET START {{data.seqstart|int}} {% endif %}{% if data.seqmin is defined and data.seqmin|int(-1) > -1%}
+SET MINVALUE {{data.seqmin|int}} {% endif %}{% if data.seqmax is defined and data.seqmax|int(-1) > -1%}
+SET MAXVALUE {{data.seqmax|int}} {% endif %}{% if data.seqcache is defined and data.seqcache|int(-1) > -1%}
+SET CACHE {{data.seqcache|int}} {% endif %};
+{% endif %}
+
+
+{###  Alter column - drop identity ###}
+{% if 'attidentity' in data and data.attidentity == '' and o_data.attidentity != '' and data.attidentity != o_data.attidentity %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} DROP IDENTITY;
+
+{% endif %}
+{###  Alter column statistics value ###}
+{% if data.attstattarget and data.attstattarget != o_data.attstattarget %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} SET STATISTICS {{data.attstattarget}};
+
+{% endif %}
+{###  Alter column storage value ###}
+{% if data.attstorage and data.attstorage != o_data.attstorage %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+    ALTER COLUMN {% if data.name %}{{conn|qtTypeIdent(data.name)}}{% else %}{{conn|qtTypeIdent(o_data.name)}}{% endif %} SET STORAGE {%if data.attstorage == 'p' %}
+PLAIN{% elif data.attstorage == 'm'%}MAIN{% elif data.attstorage == 'e'%}
+EXTERNAL{% elif data.attstorage == 'x'%}EXTENDED{% endif %};
+
+{% endif %}
+{% if data.description is defined %}
+{% if data.name %}
+COMMENT ON COLUMN {{conn|qtIdent(data.schema, data.table, data.name)}}
+{% else %}
+COMMENT ON COLUMN {{conn|qtIdent(data.schema, data.table, o_data.name)}}
+{% endif %}
+    IS {{data.description|qtLiteral}};
+
+{% endif %}
+{### Update column variables ###}
+{% if 'attoptions' in data and data.attoptions|length > 0 %}
+{% set variables = data.attoptions %}
+{% if 'deleted' in variables and variables.deleted|length > 0 %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+{% if data.name %}
+    {{ VARIABLE.UNSET(conn, 'COLUMN', data.name, variables.deleted) }}
+{% else %}
+    {{ VARIABLE.UNSET(conn, 'COLUMN', o_data.name, variables.deleted) }}
+{% endif %}
+{% endif %}
+{% if 'added' in variables and variables.added|length > 0 %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+{% if data.name %}
+    {{ VARIABLE.SET(conn, 'COLUMN', data.name, variables.added) }}
+{% else %}
+    {{ VARIABLE.SET(conn, 'COLUMN', o_data.name, variables.added) }}
+{% endif %}
+{% endif %}
+{% if 'changed' in variables and variables.changed|length > 0 %}
+ALTER TABLE {{conn|qtIdent(data.schema, data.table)}}
+{% if data.name %}
+    {{ VARIABLE.SET(conn, 'COLUMN', data.name, variables.changed) }}
+{% else %}
+    {{ VARIABLE.SET(conn, 'COLUMN', o_data.name, variables.changed) }}
+{% endif %}
+{% endif %}
+{% endif %}
+{### Update column privileges ###}
+{# Change the privileges #}
+{% if data.attacl %}
+{% if 'deleted' in data.attacl %}
+{% for priv in data.attacl.deleted %}
+{% if data.name %}
+    {{ PRIVILEGE.RESETALL(conn, data.schema, data.table, data.name, priv.grantee) }}
+{% else %}
+    {{ PRIVILEGE.RESETALL(conn, data.schema, data.table, o_data.name, priv.grantee) }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.attacl %}
+{% for priv in data.attacl.changed %}
+{% if data.name %}
+    {{ PRIVILEGE.RESETALL(conn, data.schema, data.table, data.name, priv.grantee) }}
+    {{ PRIVILEGE.APPLY(conn, data.schema, data.table, data.name, priv.grantee, priv.without_grant, priv.with_grant) }}
+{% else %}
+    {{ PRIVILEGE.RESETALL(conn, data.schema, data.table, o_data.name, priv.grantee) }}
+    {{ PRIVILEGE.APPLY(conn, data.schema, data.table, o_data.name, priv.grantee, priv.without_grant, priv.with_grant) }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.attacl %}
+{% for priv in data.attacl.added %}
+{% if data.name %}
+    {{ PRIVILEGE.APPLY(conn, data.schema, data.table, data.name, priv.grantee, priv.without_grant, priv.with_grant) }}
+{% else %}
+    {{ PRIVILEGE.APPLY(conn, data.schema, data.table, o_data.name, priv.grantee, priv.without_grant, priv.with_grant) }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endif %}
+{### Uppdate tablespace securitylabel ###}
+{# The SQL generated below will change Security Label #}
+{% if data.seclabels and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{% if data.name %}
+{{ SECLABEL.DROP(conn, 'COLUMN', data.schema, data.table, data.name, r.provider) }}
+{% else %}
+{{ SECLABEL.DROP(conn, 'COLUMN', data.schema, data.table, o_data.name, r.provider) }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{% if data.name %}
+{{ SECLABEL.APPLY(conn, 'COLUMN',data.schema, data.table, data.name, r.provider, r.label) }}
+{% else %}
+{{ SECLABEL.APPLY(conn, 'COLUMN',data.schema, data.table, o_data.name, r.provider, r.label) }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{% if data.name %}
+{{ SECLABEL.APPLY(conn, 'COLUMN',data.schema, data.table, data.name, r.provider, r.label) }}
+{% else %}
+{{ SECLABEL.APPLY(conn, 'COLUMN',data.schema, data.table, o_data.name, r.provider, r.label) }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/default/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/default/properties.sql
index 36d1e1a074..a8c1798d8a 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/default/properties.sql
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/column/sql/default/properties.sql
@@ -34,4 +34,4 @@ WHERE att.attrelid = {{tid}}::oid
     AND att.attnum > 0
 {% endif %}
     AND att.attisdropped IS FALSE
-    ORDER BY att.attnum
+    ORDER BY att.attnum;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/create.sql
new file mode 100644
index 0000000000..79a6ee8bd2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/create.sql
@@ -0,0 +1,168 @@
+{% import 'macros/schemas/security.macros' as SECLABEL %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{% import 'macros/variable.macros' as VARIABLE %}
+{% import 'column/macros/security.macros' as COLUMN_SECLABEL %}
+{% import 'column/macros/privilege.macros' as COLUMN_PRIVILEGE %}
+{% import 'table/sql/macros/constraints.macro' as CONSTRAINTS %}
+{% import 'type/macros/get_full_type_sql_format.macros' as GET_TYPE %}
+{#===========================================#}
+{#====== MAIN TABLE TEMPLATE STARTS HERE ======#}
+{#===========================================#}
+{#
+ If user has not provided any details but only name then
+ add empty bracket with table name
+#}
+{% set empty_bracket = ""%}
+{% if data.coll_inherits|length == 0 and  data.columns|length == 0 and not data.typname and not data.like_relation and data.primary_key|length == 0 and data.unique_constraint|length == 0 and data.foreign_key|length == 0 and data.check_constraint|length == 0 and data.exclude_constraint|length == 0 %}
+{% set empty_bracket = "\n(\n)"%}
+{% endif %}
+CREATE {% if data.relpersistence %}UNLOGGED {% endif %}TABLE {{conn|qtIdent(data.schema, data.name)}}{{empty_bracket}}
+{% if data.typname %}
+    OF {{ data.typname }}
+{% endif %}
+{% if data.like_relation or data.coll_inherits or data.columns|length > 0 or data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 or data.check_constraint|length > 0 or data.exclude_constraint|length > 0 %}
+(
+{% endif %}
+{% if data.like_relation %}
+    LIKE {{ data.like_relation }}{% if data.like_default_value %}
+
+        INCLUDING DEFAULTS{% endif %}{% if data.like_constraints %}
+
+        INCLUDING CONSTRAINTS{% endif %}{% if data.like_indexes %}
+
+        INCLUDING INDEXES{% endif %}{% if data.like_storage %}
+
+        INCLUDING STORAGE{% endif %}{% if data.like_comments %}
+
+        INCLUDING COMMENTS{% endif %}{% if data.columns|length > 0 %},
+{% endif %}
+
+{% endif %}
+{### Add columns ###}
+{% if data.columns and data.columns|length > 0 %}
+{% for c in data.columns %}
+{% if c.name and c.cltype and not c.inheritedfrom %}
+    {{conn|qtIdent(c.name)}} {% if is_sql %}{{c.displaytypname}}{% else %}{{ GET_TYPE.CREATE_TYPE_SQL(conn, c.cltype, c.attlen, c.attprecision, c.hasSqrBracket) }}{% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.attnotnull %} NOT NULL{% endif %}{% if c.defval %} DEFAULT {{c.defval}}{% endif %}
+{% if c.attidentity and c.attidentity == 'a' %} GENERATED ALWAYS AS IDENTITY{% elif c.attidentity and c.attidentity == 'd' %} GENERATED BY DEFAULT AS IDENTITY{% endif %}
+{% if c.seqincrement or c.seqcycle or c.seqincrement or c.seqstart or c.seqmin or c.seqmax or c.seqcache %} ( {% endif %}
+{% if c.seqincrement is defined and c.seqcycle %}
+CYCLE {% endif %}{% if c.seqincrement is defined and c.seqincrement|int(-1) > -1 %}
+INCREMENT {{c.seqincrement|int}} {% endif %}{% if c.seqstart is defined and c.seqstart|int(-1) > -1%}
+START {{c.seqstart|int}} {% endif %}{% if c.seqmin is defined and c.seqmin|int(-1) > -1%}
+MINVALUE {{c.seqmin|int}} {% endif %}{% if c.seqmax is defined and c.seqmax|int(-1) > -1%}
+MAXVALUE {{c.seqmax|int}} {% endif %}{% if c.seqcache is defined and c.seqcache|int(-1) > -1%}
+CACHE {{c.seqcache|int}} {% endif %}
+{% if c.seqincrement or c.seqcycle or c.seqincrement or c.seqstart or c.seqmin or c.seqmax or c.seqcache %}){% endif %}
+{% if not loop.last %},
+{% endif %}
+{% endif %}
+{% endfor %}
+{% endif %}
+{# Macro to render for constraints #}
+{% if data.primary_key|length > 0 %}{% if data.columns|length > 0 %},{% endif %}
+{{CONSTRAINTS.PRIMARY_KEY(conn, data.primary_key[0])}}{% endif %}{% if data.unique_constraint|length > 0 %}{% if data.columns|length > 0 or data.primary_key|length > 0 %},{% endif %}
+{{CONSTRAINTS.UNIQUE(conn, data.unique_constraint)}}{% endif %}{% if data.foreign_key|length > 0 %}{% if data.columns|length > 0 or data.primary_key|length > 0 or data.unique_constraint|length > 0 %},{% endif %}
+{{CONSTRAINTS.FOREIGN_KEY(conn, data.foreign_key)}}{% endif %}{% if data.check_constraint|length > 0 %}{% if data.columns|length > 0 or data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 %},{% endif %}
+{{CONSTRAINTS.CHECK(conn, data.check_constraint)}}{% endif %}{% if data.exclude_constraint|length > 0 %}{% if data.columns|length > 0 or data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 or data.check_constraint|length > 0 %},{% endif %}
+{{CONSTRAINTS.EXCLUDE(conn, data.exclude_constraint)}}{% endif %}
+{% if data.like_relation or data.coll_inherits or data.columns|length > 0 or data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 or data.check_constraint|length > 0 or data.exclude_constraint|length > 0 %}
+
+){% endif %}{% if data.relkind is defined and data.relkind == 'p' %} PARTITION BY {{ data.partition_scheme }} {% endif %}
+
+{### If we are inheriting it from another table(s) ###}
+{% if data.coll_inherits %}
+    INHERITS ({% for val in data.coll_inherits %}{% if loop.index != 1 %}, {% endif %}{{val}}{% endfor %})
+{% endif %}
+WITH (
+    OIDS = {% if data.relhasoids %}TRUE{% else %}FALSE{% endif %}{% if data.fillfactor %},
+    FILLFACTOR = {{ data.fillfactor }}{% endif %}{% if data.autovacuum_custom %},
+    autovacuum_enabled = {% if data.autovacuum_enabled %}TRUE{% else %}FALSE{% endif %}{% endif %}{% if data.toast_autovacuum %},
+    toast.autovacuum_enabled = {% if data.toast_autovacuum_enabled %}TRUE{% else %}FALSE{% endif %}
+{% endif %}{% if data.autovacuum_enabled and data.vacuum_table|length > 0 %}
+{% for opt in data.vacuum_table %}{% if opt.name and opt.value %}
+,
+    {{opt.name}} = {{opt.value}}{% endif %}
+{% endfor %}{% endif %}{% if data.toast_autovacuum_enabled and data.vacuum_toast|length > 0 %}
+{% for opt in data.vacuum_toast %}{% if opt.name and opt.value %}
+,
+    toast.{{opt.name}} = {{opt.value}}{% endif %}
+{% endfor %}{% endif %}
+
+{### SQL for Tablespace ###}
+{% if data.spcname %}
+)
+TABLESPACE {{ conn|qtIdent(data.spcname) }};
+{% else %}
+);
+{% endif %}
+{### Alter SQL for Owner ###}
+{% if data.relowner %}
+
+ALTER TABLE {{conn|qtIdent(data.schema, data.name)}}
+    OWNER to {{conn|qtIdent(data.relowner)}};
+{% endif %}
+{### Security Labels on Table ###}
+{% if data.seclabels and data.seclabels|length > 0 %}
+
+{% for r in data.seclabels %}
+{{ SECLABEL.SET(conn, 'TABLE', data.name, r.provider, r.label, data.schema) }}
+{% endfor %}
+{% endif %}
+{###  ACL on Table ###}
+{% if data.relacl %}
+
+{% for priv in data.relacl %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{### SQL for COMMENT ###}
+{% if data.description %}
+COMMENT ON TABLE {{conn|qtIdent(data.schema, data.name)}}
+    IS {{data.description|qtLiteral}};
+{% endif %}
+{#===========================================#}
+{#====== MAIN TABLE TEMPLATE ENDS HERE ======#}
+{#===========================================#}
+{#===========================================#}
+{#  COLUMN SPECIFIC TEMPLATES STARTS HERE    #}
+{#===========================================#}
+{% if data.columns and data.columns|length > 0 %}
+{% for c in data.columns %}
+{% if c.description %}
+
+COMMENT ON COLUMN {{conn|qtIdent(data.schema, data.name, c.name)}}
+    IS {{c.description|qtLiteral}};
+{% endif %}
+{###  Add variables to column ###}
+{% if c.attoptions and c.attoptions|length > 0 %}
+
+ALTER TABLE {{conn|qtIdent(data.schema, data.name)}}
+    {{ VARIABLE.SET(conn, 'COLUMN', c.name, c.attoptions) }}
+{% endif %}
+{###  ACL ###}
+{% if c.attacl and c.attacl|length > 0 %}
+
+{% for priv in c.attacl %}
+    {{ COLUMN_PRIVILEGE.APPLY(conn, data.schema, data.name, c.name, priv.grantee, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+{% endif %}
+{###  Security Lables ###}
+{% if c.seclabels and c.seclabels|length > 0 %}
+
+{% for r in c.seclabels %}
+{{ COLUMN_SECLABEL.APPLY(conn, 'COLUMN',data.schema, data.name, c.name, r.provider, r.label) }}
+{% endfor %}
+{% endif %}
+{% endfor %}
+{% endif %}
+{#===========================================#}
+{#   COLUMN SPECIFIC TEMPLATES ENDS HERE     #}
+{#===========================================#}
+{#======================================#}
+{#   CONSTRAINTS SPECIFIC TEMPLATES     #}
+{#======================================#}
+{{CONSTRAINTS.CONSTRAINT_COMMENTS(conn, data.schema, data.name, data.primary_key)}}
+{{CONSTRAINTS.CONSTRAINT_COMMENTS(conn, data.schema, data.name, data.unique_constraint)}}
+{{CONSTRAINTS.CONSTRAINT_COMMENTS(conn, data.schema, data.name, data.foreign_key)}}
+{{CONSTRAINTS.CONSTRAINT_COMMENTS(conn, data.schema, data.name, data.check_constraint)}}
+{{CONSTRAINTS.CONSTRAINT_COMMENTS(conn, data.schema, data.name, data.exclude_constraint)}}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/get_columns_for_table.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/get_columns_for_table.sql
new file mode 100644
index 0000000000..f5ae9942de
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/sql/10_plus/get_columns_for_table.sql
@@ -0,0 +1,16 @@
+SELECT
+    a.attname AS name, format_type(a.atttypid, NULL) AS cltype, a.attidentity as clidentity,
+    quote_ident(n.nspname)||'.'||quote_ident(c.relname) as inheritedfrom,
+    c.oid as inheritedid
+FROM
+    pg_class c
+JOIN
+    pg_namespace n ON c.relnamespace=n.oid
+JOIN
+    pg_attribute a ON a.attrelid = c.oid AND NOT a.attisdropped AND a.attnum > 0
+WHERE
+{% if tid %}
+    c.oid = {{tid}}::OID
+{% else %}
+    c.relname = {{tname|qtLiteral}}
+{% endif %}
diff --git a/web/pgadmin/browser/utils.py b/web/pgadmin/browser/utils.py
index 18d73ee4c7..92f1cddb6c 100644
--- a/web/pgadmin/browser/utils.py
+++ b/web/pgadmin/browser/utils.py
@@ -360,7 +360,7 @@ def children(self, **kwargs):
             )
         )
 
-    def get_dependencies(self, conn, object_id, where=None):
+    def get_dependencies(self, conn, object_id, where=None, show_system_objects=None):
         """
         This function is used to fetch the dependencies for the selected node.
 
@@ -383,7 +383,7 @@ def get_dependencies(self, conn, object_id, where=None):
         query = render_template("/".join([sql_path, 'dependencies.sql']),
                                 where_clause=where_clause)
         # fetch the dependency for the selected object
-        dependencies = self.__fetch_dependency(conn, query)
+        dependencies = self.__fetch_dependency(conn, query, show_system_objects)
 
         # fetch role dependencies
         if where_clause.find('subid') < 0:
@@ -440,7 +440,7 @@ def get_dependents(self, conn, object_id, where=None):
 
         return dependents
 
-    def __fetch_dependency(self, conn, query):
+    def __fetch_dependency(self, conn, query, show_system_objects=None):
         """
         This function is used to fetch the dependency for the selected node.
 
@@ -545,13 +545,15 @@ def __fetch_dependency(self, conn, query):
                 ref_name += _ref_name
 
             dep_type = ''
+            if show_system_objects is None:
+                show_system_objects = self.blueprint.show_system_objects
             if dep_str[0] in dep_types:
 
                 # if dep_type is present in the dep_types dictionary, but it's
                 # value is None then it requires special handling.
                 if dep_types[dep_str[0]] is None:
                     if dep_str[0] == 'i':
-                        if self.blueprint.show_system_objects:
+                        if show_system_objects:
                             dep_type = 'internal'
                         else:
                             continue
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
index ef69a8d94f..596a4b486b 100644
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ b/web/pgadmin/static/js/backform.pgadmin.js
@@ -2090,6 +2090,7 @@ define([
       Backform.Control.prototype.initialize.apply(
         this, arguments
       );
+      debugger;
       Backform.Dialog.prototype.initialize.apply(
         this, [{
           schema: opts.field.get('schema'),
diff --git a/web/pgadmin/static/scss/_backgrid.overrides.scss b/web/pgadmin/static/scss/_backgrid.overrides.scss
index 064ffe7b49..b0b7475a54 100644
--- a/web/pgadmin/static/scss/_backgrid.overrides.scss
+++ b/web/pgadmin/static/scss/_backgrid.overrides.scss
@@ -234,6 +234,10 @@ span.form-control:disabled {
     & .tab-pane {
       padding: 0.5rem;
     }
+
+    fieldset.inline-fieldset {
+      background: $color-bg-theme;
+    }
 }
 .subnode-footer {
     height: 38px;
