Skip to content

Commit b08e90e

Browse files
Add support for type constructors for PostGIS spatial types. #2256
1 parent 75dc42c commit b08e90e

File tree

21 files changed

+426
-20
lines changed

21 files changed

+426
-20
lines changed

.github/workflows/run-python-tests-epas.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848
if: ${{ matrix.os == 'ubuntu-22.04' }}
4949
run: |
5050
sudo apt update
51-
sudo apt install -y libpq-dev libffi-dev libssl-dev libkrb5-dev zlib1g-dev edb-as${{ matrix.pgver }}-server edb-as${{ matrix.pgver }}-server-pldebugger
51+
sudo apt install -y libpq-dev libffi-dev libssl-dev libkrb5-dev zlib1g-dev edb-as${{ matrix.pgver }}-server edb-as${{ matrix.pgver }}-server-pldebugger edb-as${{ matrix.pgver }}-postgis34
5252
5353
- name: Install pgagent on Linux
5454
if: ${{ matrix.os == 'ubuntu-22.04' && matrix.pgver <= 16 }}
@@ -105,6 +105,10 @@ jobs:
105105
- name: Create pgagent extension on Linux
106106
if: ${{ matrix.os == 'ubuntu-22.04' && matrix.pgver <= 16 }}
107107
run: psql -U enterprisedb -d postgres -p 58${{ matrix.pgver }} -c 'CREATE EXTENSION IF NOT EXISTS pgagent;'
108+
109+
- name: Create postgis extension on Linux
110+
if: ${{ matrix.os == 'ubuntu-22.04' && matrix.pgver <= 16 }}
111+
run: psql -U enterprisedb -d postgres -p 58${{ matrix.pgver }} -c 'CREATE EXTENSION IF NOT EXISTS postgis;'
108112

109113
- name: Install Python dependencies on Linux
110114
if: ${{ matrix.os == 'ubuntu-22.04' }}

.github/workflows/run-python-tests-pg.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
if: ${{ matrix.os == 'ubuntu-22.04' }}
5252
run: |
5353
sudo apt update
54-
sudo apt install -y libpq-dev libffi-dev libssl-dev libkrb5-dev zlib1g-dev postgresql-${{ matrix.pgver }} postgresql-${{ matrix.pgver }}-pldebugger pgagent
54+
sudo apt install -y libpq-dev libffi-dev libssl-dev libkrb5-dev zlib1g-dev postgresql-${{ matrix.pgver }} postgresql-${{ matrix.pgver }}-pldebugger pgagent postgresql-${{ matrix.pgver }}-postgis-3
5555
5656
- name: Install platform dependencies on macOS
5757
if: ${{ matrix.os == 'macos-latest' }}
@@ -113,6 +113,7 @@ jobs:
113113
114114
psql -U postgres -p 59${{ matrix.pgver }} -c 'CREATE EXTENSION pgagent;'
115115
psql -U postgres -p 59${{ matrix.pgver }} -c 'CREATE EXTENSION pldbgapi;'
116+
psql -U postgres -p 59${{ matrix.pgver }} -c 'CREATE EXTENSION postgis;'
116117
117118
- name: Start PostgreSQL on macOS
118119
if: ${{ matrix.os == 'macos-latest' }}

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: 43 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,42 @@ 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+
visible: (state) => {
303+
return (state.cltype == 'geometry' || state.cltype == 'geography');
304+
}
305+
},{
306+
id:'srid', label: gettext('SRID'), deps: ['cltype'],
307+
group: gettext('Definition'), type: 'int',
308+
depChange: (state) => {
309+
let cltype = state.cltype;
310+
if (cltype != 'geometry' && cltype != 'geography') {
311+
return {
312+
...state,
313+
srid: null
314+
};
315+
}
316+
},
317+
disabled: function(state) {
318+
return !(state.cltype == 'geometry' || state.cltype == 'geography');
319+
},
320+
visible: function(state) {
321+
return (state.cltype == 'geometry' || state.cltype == 'geography');
322+
}
281323
},{
282324
id: 'attlen', label: gettext('Length/Precision'),
283325
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: 29 additions & 8 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):
@@ -448,19 +449,24 @@ def fetch_length_precision(data):
448449
data['attlen'] = None
449450
data['attprecision'] = None
450451

451-
import re
452+
if 'typname' in data and (data['typname'] in ('geometry', 'geography')):
453+
# If we have geometry column
454+
parmas = parse_params(data['cltype'])
455+
if parmas:
456+
data['geometry'] = parmas[0]
457+
data['srid'] = parmas[1]
458+
else:
459+
parmas = parse_params(fulltype)
452460

453461
# If we have length & precision both
454462
if length and precision:
455-
match_obj = re.search(r'(\d+),(\d+)', fulltype)
456-
if match_obj:
457-
data['attlen'] = match_obj.group(1)
458-
data['attprecision'] = match_obj.group(2)
463+
if parmas:
464+
data['attlen'] = parmas[0]
465+
data['attprecision'] = parmas[1]
459466
elif length:
460467
# If we have length only
461-
match_obj = re.search(r'(\d+)', fulltype)
462-
if match_obj:
463-
data['attlen'] = match_obj.group(1)
468+
if parmas:
469+
data['attlen'] = parmas[0]
464470
data['attprecision'] = None
465471

466472
return data
@@ -474,3 +480,18 @@ def parse_column_variables(col_variables):
474480
k, v = spcoption.split('=')
475481
spcoptions.append({'name': k, 'value': v})
476482
return spcoptions
483+
484+
485+
def parse_params(fulltype):
486+
"""
487+
This function will fetch length and precision details
488+
from fulltype.
489+
490+
:param fulltype: Full type.
491+
:param data: Data.
492+
"""
493+
494+
match_obj = re.search(r'\((\d*[a-zA-Z]*),?(\d*)\)', fulltype)
495+
if match_obj:
496+
return [match_obj.group(1), match_obj.group(2)]
497+
return False

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 %}

0 commit comments

Comments
 (0)