Skip to content

Commit 23eeb1f

Browse files
Added support for type constructors for PostGIS spatial types. #2256
1 parent 31b1af2 commit 23eeb1f

File tree

16 files changed

+366
-11
lines changed

16 files changed

+366
-11
lines changed

web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ class TableView(BaseTableView, DataTypeReader, SchemaDiffTableCompare):
308308
'count_rows': [{'get': 'count_rows'}],
309309
'compare': [{'get': 'compare'}, {'get': 'compare'}],
310310
'get_op_class': [{'get': 'get_op_class'}, {'get': 'get_op_class'}],
311+
'get_geometry_types': [
312+
{'get': 'geometry_types'},
313+
{'get': 'geometry_types'}],
311314
})
312315

313316
@BaseTableView.check_precondition
@@ -695,6 +698,21 @@ def types(self, gid, sid, did, scid, tid=None, clid=None):
695698
status=200
696699
)
697700

701+
@BaseTableView.check_precondition
702+
def geometry_types(self, gid, sid, did, scid, tid=None, clid=None):
703+
"""
704+
Returns:
705+
This function will return list of geometry types available for
706+
column node for node-ajax-control
707+
"""
708+
status, types = self.get_geometry_types(self.conn)
709+
if not status:
710+
return internal_server_error(errormsg=types)
711+
return make_json_response(
712+
data=types,
713+
status=200
714+
)
715+
698716
@BaseTableView.check_precondition
699717
def get_columns(self, gid, sid, did, scid, tid=None):
700718
"""

web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.ui.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@ export function getNodeColumnSchema(treeNodeInfo, itemNodeData, pgBrowser) {
2424
cacheLevel: 'table',
2525
}),
2626
()=>getNodeAjaxOptions('get_collations', pgBrowser.Nodes['collation'], treeNodeInfo, itemNodeData),
27+
()=>getNodeAjaxOptions('get_geometry_types', pgBrowser.Nodes['table'], treeNodeInfo, itemNodeData, {
28+
cacheLevel: 'table',
29+
}),
2730
);
2831
}
2932

3033
export default class ColumnSchema extends BaseUISchema {
31-
constructor(getPrivilegeRoleSchema, nodeInfo, cltypeOptions, collspcnameOptions, inErd=false) {
34+
constructor(getPrivilegeRoleSchema, nodeInfo, cltypeOptions, collspcnameOptions, geometryTypes, inErd=false) {
3235
super({
3336
name: undefined,
3437
attowner: undefined,
@@ -60,12 +63,15 @@ export default class ColumnSchema extends BaseUISchema {
6063
seqcycle: undefined,
6164
colconstype: 'n',
6265
genexpr: undefined,
66+
srid: null,
67+
geometry: null,
6368
});
6469

6570
this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
6671
this.nodeInfo = nodeInfo;
6772
this.cltypeOptions = cltypeOptions;
6873
this.collspcnameOptions = collspcnameOptions;
74+
this.geometryTypes = geometryTypes;
6975
this.inErd = inErd;
7076

7177
this.datatypes = [];
@@ -278,6 +284,36 @@ export default class ColumnSchema extends BaseUISchema {
278284
}
279285
return false;
280286
},
287+
},{
288+
id:'geometry', label: gettext('Geometry Type'), deps: ['cltype'],
289+
group: gettext('Definition'), type: 'select', options: this.geometryTypes,
290+
disabled: (state) => {
291+
return !(state.cltype == 'geometry' || state.cltype == 'geography');
292+
},
293+
depChange: (state) => {
294+
let cltype = state.cltype;
295+
if (cltype != 'geometry' && cltype != 'geography') {
296+
return {
297+
...state,
298+
geometry: null
299+
};
300+
}
301+
}
302+
},{
303+
id:'srid', label: gettext('SRID'), deps: ['cltype'],
304+
group: gettext('Definition'), type: 'int',
305+
depChange: (state) => {
306+
let cltype = state.cltype;
307+
if (cltype != 'geometry' && cltype != 'geography') {
308+
return {
309+
...state,
310+
srid: null
311+
};
312+
}
313+
},
314+
disabled: function(state) {
315+
return !(state.cltype == 'geometry' || state.cltype == 'geography');
316+
},
281317
},{
282318
id: 'attlen', label: gettext('Length/Precision'),
283319
deps: ['cltype'], type: 'int', group: gettext('Definition'), width: 120, enableResizing: false,

web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/utils.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from pgadmin.browser.server_groups.servers.databases.utils \
2121
import make_object_name
2222
from functools import wraps
23+
import re
2324

2425

2526
def get_template_path(f):
@@ -132,6 +133,8 @@ def column_formatter(conn, tid, clid, data, edit_types_list=None,
132133
# Fetch length and precision
133134
data = fetch_length_precision(data)
134135

136+
data = fetch_geometry_details(data)
137+
135138
# We need to fetch inherited tables for each table
136139
is_error, errmsg = _fetch_inherited_tables(
137140
tid, data, fetch_inherited_tables, template_path, conn)
@@ -448,8 +451,6 @@ def fetch_length_precision(data):
448451
data['attlen'] = None
449452
data['attprecision'] = None
450453

451-
import re
452-
453454
# If we have length & precision both
454455
if length and precision:
455456
match_obj = re.search(r'(\d+),(\d+)', fulltype)
@@ -474,3 +475,12 @@ def parse_column_variables(col_variables):
474475
k, v = spcoption.split('=')
475476
spcoptions.append({'name': k, 'value': v})
476477
return spcoptions
478+
479+
480+
def fetch_geometry_details(data):
481+
if 'typname' in data and (data['typname'] in ('geometry', 'geography')):
482+
match_obj = re.search(r'([a-zA-Z]+),(\d+)', data['cltype'])
483+
if match_obj:
484+
data['geometry'] = match_obj.group(1)
485+
data['srid'] = match_obj.group(2)
486+
return data

web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/11_plus/create.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ CREATE {% if data.relpersistence %}UNLOGGED {% endif %}TABLE{% if add_not_exists
4646
{% if data.columns and data.columns|length > 0 %}
4747
{% for c in data.columns %}
4848
{% if c.name and c.cltype %}
49-
{% if c.inheritedfromtable %}-- Inherited from table {{c.inheritedfromtable}}: {% elif c.inheritedfromtype %}-- Inherited from type {{c.inheritedfromtype}}: {% endif %}{{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 is defined and c.defval is not none and c.defval != '' %} DEFAULT {{c.defval}}{% endif %}
49+
{% if c.inheritedfromtable %}-- Inherited from table {{c.inheritedfromtable}}: {% elif c.inheritedfromtype %}-- Inherited from type {{c.inheritedfromtype}}: {% endif %}{{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.geometry and not is_sql %}({{c.geometry}}{% if c.srid %},{{c.srid}}{% endif %}){% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.attnotnull %} NOT NULL{% endif %}{% if c.defval is defined and c.defval is not none and c.defval != '' %} DEFAULT {{c.defval}}{% endif %}
5050
{% if c.colconstype == 'i' and c.attidentity and c.attidentity != '' %}
5151
{% if c.attidentity == 'a' %} GENERATED ALWAYS AS IDENTITY{% elif c.attidentity == 'd' %} GENERATED BY DEFAULT AS IDENTITY{% endif %}
5252
{% if c.seqincrement or c.seqcycle or c.seqincrement or c.seqstart or c.seqmin or c.seqmax or c.seqcache %} ( {% endif %}

web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/12_plus/create.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ CREATE {% if data.relpersistence %}UNLOGGED {% endif %}TABLE{% if add_not_exists
5252
{% if data.columns and data.columns|length > 0 %}
5353
{% for c in data.columns %}
5454
{% if c.name and c.cltype %}
55-
{% if c.inheritedfromtable %}-- Inherited from table {{c.inheritedfromtable}}: {% elif c.inheritedfromtype %}-- Inherited from type {{c.inheritedfromtype}}: {% endif %}{{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 is defined and c.defval is not none and c.defval != '' and c.colconstype != 'g' %} DEFAULT {{c.defval}}{% endif %}
55+
{% if c.inheritedfromtable %}-- Inherited from table {{c.inheritedfromtable}}: {% elif c.inheritedfromtype %}-- Inherited from type {{c.inheritedfromtype}}: {% endif %}{{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.geometry and not is_sql %}({{c.geometry}}{% if c.srid %},{{c.srid}}{% endif %}){% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.attnotnull %} NOT NULL{% endif %}{% if c.defval is defined and c.defval is not none and c.defval != '' and c.colconstype != 'g' %} DEFAULT {{c.defval}}{% endif %}
5656
{% if c.colconstype == 'i' and c.attidentity and c.attidentity != '' %}
5757
{% if c.attidentity == 'a' %} GENERATED ALWAYS AS IDENTITY{% elif c.attidentity == 'd' %} GENERATED BY DEFAULT AS IDENTITY{% endif %}
5858
{% if c.seqincrement or c.seqcycle or c.seqincrement or c.seqstart or c.seqmin or c.seqmax or c.seqcache %} ( {% endif %}

web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/14_plus/create.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ CREATE {% if data.relpersistence %}UNLOGGED {% endif %}TABLE{% if add_not_exists
5454
{% if data.columns and data.columns|length > 0 %}
5555
{% for c in data.columns %}
5656
{% if c.name and c.cltype %}
57-
{% if c.inheritedfromtable %}-- Inherited from table {{c.inheritedfromtable}}: {% elif c.inheritedfromtype %}-- Inherited from type {{c.inheritedfromtype}}: {% endif %}{{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.attcompression is defined and c.attcompression is not none and c.attcompression != '' %} COMPRESSION {{c.attcompression}}{% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.attnotnull %} NOT NULL{% endif %}{% if c.defval is defined and c.defval is not none and c.defval != '' and c.colconstype != 'g' %} DEFAULT {{c.defval}}{% endif %}
57+
{% if c.inheritedfromtable %}-- Inherited from table {{c.inheritedfromtable}}: {% elif c.inheritedfromtype %}-- Inherited from type {{c.inheritedfromtype}}: {% endif %}{{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.geometry and not is_sql %}({{c.geometry}}{% if c.srid %},{{c.srid}}{% endif %}){% endif %}{% if c.attcompression is defined and c.attcompression is not none and c.attcompression != '' %} COMPRESSION {{c.attcompression}}{% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.attnotnull %} NOT NULL{% endif %}{% if c.defval is defined and c.defval is not none and c.defval != '' and c.colconstype != 'g' %} DEFAULT {{c.defval}}{% endif %}
5858
{% if c.colconstype == 'i' and c.attidentity and c.attidentity != '' %}
5959
{% if c.attidentity == 'a' %} GENERATED ALWAYS AS IDENTITY{% elif c.attidentity == 'd' %} GENERATED BY DEFAULT AS IDENTITY{% endif %}
6060
{% if c.seqincrement or c.seqcycle or c.seqincrement or c.seqstart or c.seqmin or c.seqmax or c.seqcache %} ( {% endif %}

web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/16_plus/create.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ CREATE {% if data.relpersistence %}UNLOGGED {% endif %}TABLE{% if add_not_exists
5454
{% if data.columns and data.columns|length > 0 %}
5555
{% for c in data.columns %}
5656
{% if c.name and c.cltype %}
57-
{% if c.inheritedfromtable %}-- Inherited from table {{c.inheritedfromtable}}: {% elif c.inheritedfromtype %}-- Inherited from type {{c.inheritedfromtype}}: {% endif %}{{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.attstorage is defined and c.attstorage != c.defaultstorage%} STORAGE {%if c.attstorage == 'p' %}PLAIN{% elif c.attstorage == 'm'%}MAIN{% elif c.attstorage == 'e'%}EXTERNAL{% elif c.attstorage == 'x'%}EXTENDED{% elif c.attstorage == 'd'%}DEFAULT{% endif %}{% endif %}{% if c.attcompression is defined and c.attcompression is not none and c.attcompression != '' %} COMPRESSION {{c.attcompression}}{% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.attnotnull %} NOT NULL{% endif %}{% if c.defval is defined and c.defval is not none and c.defval != '' and c.colconstype != 'g' %} DEFAULT {{c.defval}}{% endif %}
57+
{% if c.inheritedfromtable %}-- Inherited from table {{c.inheritedfromtable}}: {% elif c.inheritedfromtype %}-- Inherited from type {{c.inheritedfromtype}}: {% endif %}{{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.geometry and not is_sql %}({{c.geometry}}{% if c.srid %},{{c.srid}}{% endif %}){% endif %}{%if c.attstorage is defined and c.attstorage != c.defaultstorage%} STORAGE {%if c.attstorage == 'p' %}PLAIN{% elif c.attstorage == 'm'%}MAIN{% elif c.attstorage == 'e'%}EXTERNAL{% elif c.attstorage == 'x'%}EXTENDED{% elif c.attstorage == 'd'%}DEFAULT{% endif %}{% endif %}{% if c.attcompression is defined and c.attcompression is not none and c.attcompression != '' %} COMPRESSION {{c.attcompression}}{% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.attnotnull %} NOT NULL{% endif %}{% if c.defval is defined and c.defval is not none and c.defval != '' and c.colconstype != 'g' %} DEFAULT {{c.defval}}{% endif %}
5858
{% if c.colconstype == 'i' and c.attidentity and c.attidentity != '' %}
5959
{% if c.attidentity == 'a' %} GENERATED ALWAYS AS IDENTITY{% elif c.attidentity == 'd' %} GENERATED BY DEFAULT AS IDENTITY{% endif %}
6060
{% if c.seqincrement or c.seqcycle or c.seqincrement or c.seqstart or c.seqmin or c.seqmax or c.seqcache %} ( {% endif %}

web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/create.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ CREATE {% if data.relpersistence %}UNLOGGED {% endif %}TABLE{% if add_not_exists
4646
{% if data.columns and data.columns|length > 0 %}
4747
{% for c in data.columns %}
4848
{% if c.name and c.cltype %}
49-
{% if c.inheritedfromtable %}-- Inherited from table {{c.inheritedfromtable}}: {% elif c.inheritedfromtype %}-- Inherited from type {{c.inheritedfromtype}}: {% endif %}{{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 is defined and c.defval is not none and c.defval != '' %} DEFAULT {{c.defval}}{% endif %}
49+
{% if c.inheritedfromtable %}-- Inherited from table {{c.inheritedfromtable}}: {% elif c.inheritedfromtype %}-- Inherited from type {{c.inheritedfromtype}}: {% endif %}{{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.geometry and not is_sql %}({{c.geometry}}{% if c.srid %},{{c.srid}}{% endif %}){% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.attnotnull %} NOT NULL{% endif %}{% if c.defval is defined and c.defval is not none and c.defval != '' %} DEFAULT {{c.defval}}{% endif %}
5050
{% if c.colconstype == 'i' and c.attidentity and c.attidentity != '' %}
5151
{% if c.attidentity == 'a' %} GENERATED ALWAYS AS IDENTITY{% elif c.attidentity == 'd' %} GENERATED BY DEFAULT AS IDENTITY{% endif %}
5252
{% if c.seqincrement or c.seqcycle or c.seqincrement or c.seqstart or c.seqmin or c.seqmax or c.seqcache %} ( {% endif %}

web/pgadmin/browser/server_groups/servers/databases/schemas/tables/tests/table_test_data.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,5 +2157,52 @@
21572157
},
21582158
"is_list": false
21592159
}
2160+
],
2161+
"table_create_geometry": [
2162+
{
2163+
"name": "Create: Add Table with geometry columns",
2164+
"is_positive_test": true,
2165+
"inventory_data": {},
2166+
"test_data": {
2167+
"description": "Create Table API Test",
2168+
"columns": [
2169+
{
2170+
"name": "id",
2171+
"cltype": "bigint",
2172+
"attacl": [],
2173+
"is_primary_key": false,
2174+
"attnotnull": true,
2175+
"attlen": null,
2176+
"attprecision": null,
2177+
"attoptions": [],
2178+
"seclabels": [],
2179+
"colconstype": "n",
2180+
"attidentity": "a"
2181+
},
2182+
{
2183+
"name": "geom",
2184+
"cltype": "geometry",
2185+
"attacl": [],
2186+
"is_primary_key": false,
2187+
"attnotnull": true,
2188+
"attlen": null,
2189+
"attprecision": null,
2190+
"attoptions": [],
2191+
"seclabels": [],
2192+
"colconstype": "n",
2193+
"attidentity": "a",
2194+
"geometry": "Point",
2195+
"srid": "2154"
2196+
}
2197+
]
2198+
},
2199+
"mocking_required": false,
2200+
"mock_data": {},
2201+
"expected_data": {
2202+
"status_code": 200,
2203+
"error_msg": null,
2204+
"test_result_data": {}
2205+
}
2206+
}
21602207
]
21612208
}

0 commit comments

Comments
 (0)