mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Fix creation of tables and columns in GPDB. Fixes #3099
This commit is contained in:
committed by
Dave Page
parent
1a958a3951
commit
15862e903a
@@ -20,6 +20,7 @@ from pgadmin.browser.server_groups.servers.databases.schemas.utils \
|
||||
from pgadmin.browser.utils import PGChildNodeView
|
||||
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
||||
make_response as ajax_response, gone
|
||||
from pgadmin.utils.compile_template_name import compile_template_path
|
||||
from pgadmin.utils.driver import get_driver
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
from pgadmin.utils import IS_PY2
|
||||
@@ -189,7 +190,11 @@ class CollationView(PGChildNodeView):
|
||||
)
|
||||
self.conn = self.manager.connection(did=kwargs['did'])
|
||||
# Set the template path for the SQL scripts
|
||||
self.template_path = 'collation/sql/#{0}#'.format(self.manager.version)
|
||||
self.template_path = compile_template_path(
|
||||
'collation/sql/',
|
||||
self.manager.server_type,
|
||||
self.manager.version
|
||||
)
|
||||
|
||||
return f(*args, **kwargs)
|
||||
return wrap
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
SELECT 'pg_catalog.' || quote_ident(collate_setting.value) AS copy_collation
|
||||
FROM (
|
||||
SELECT setting AS value
|
||||
FROM pg_settings
|
||||
WHERE name='lc_collate'
|
||||
) collate_setting;
|
||||
@@ -22,6 +22,7 @@ from pgadmin.browser.server_groups.servers.databases.utils import \
|
||||
from pgadmin.browser.utils import PGChildNodeView
|
||||
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
||||
make_response as ajax_response, gone
|
||||
from pgadmin.utils.compile_template_name import compile_template_path
|
||||
from pgadmin.utils.driver import get_driver
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
from pgadmin.utils import IS_PY2
|
||||
@@ -267,7 +268,11 @@ class DomainView(PGChildNodeView, DataTypeReader):
|
||||
self.qtIdent = driver.qtIdent
|
||||
|
||||
# we will set template path for sql scripts
|
||||
self.template_path = 'domains/sql/#{0}#'.format(self.manager.version)
|
||||
self.template_path = compile_template_path(
|
||||
'domains/sql/',
|
||||
self.manager.server_type,
|
||||
self.manager.version
|
||||
)
|
||||
|
||||
return f(*args, **kwargs)
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
SELECT 'pg_catalog.' || quote_ident(collate_setting.value) AS copy_collation
|
||||
FROM (
|
||||
SELECT setting AS value
|
||||
FROM pg_settings
|
||||
WHERE name='lc_collate'
|
||||
) collate_setting;
|
||||
@@ -27,6 +27,7 @@ from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
|
||||
from pgadmin.browser.utils import PGChildNodeView
|
||||
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
||||
make_response as ajax_response, gone
|
||||
from pgadmin.utils.compile_template_name import compile_template_path
|
||||
from pgadmin.utils.driver import get_driver
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
from pgadmin.utils import IS_PY2
|
||||
@@ -344,7 +345,11 @@ class ForeignTableView(PGChildNodeView, DataTypeReader):
|
||||
|
||||
# Set template path for sql scripts depending
|
||||
# on the server version.
|
||||
self.template_path = 'foreign_tables/sql/#{0}#'.format(self.manager.version)
|
||||
self.template_path = compile_template_path(
|
||||
'foreign_tables/sql/',
|
||||
self.manager.server_type,
|
||||
self.manager.version
|
||||
)
|
||||
|
||||
return f(*args, **kwargs)
|
||||
return wrap
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
SELECT 'pg_catalog.' || quote_ident(collate_setting.value) AS copy_collation
|
||||
FROM (
|
||||
SELECT setting AS value
|
||||
FROM pg_settings
|
||||
WHERE name='lc_collate'
|
||||
) collate_setting;
|
||||
@@ -618,7 +618,7 @@ class TableView(BaseTableView, DataTypeReader, VacuumSettings):
|
||||
show_system_objects=self.blueprint.show_system_objects
|
||||
)
|
||||
|
||||
status, types = self.get_types(self.conn, condition, True)
|
||||
status, types = self.get_types(self.conn, condition, True, sid)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=types)
|
||||
|
||||
@@ -20,6 +20,7 @@ from pgadmin.browser.server_groups.servers.databases.schemas.tables.partitions i
|
||||
from pgadmin.browser.utils import PGChildNodeView
|
||||
from pgadmin.utils.ajax import make_json_response, internal_server_error, \
|
||||
make_response as ajax_response, gone
|
||||
from pgadmin.utils.compile_template_name import compile_template_path
|
||||
from pgadmin.utils.driver import get_driver
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
from pgadmin.utils import IS_PY2
|
||||
@@ -249,7 +250,11 @@ class IndexesView(PGChildNodeView):
|
||||
kwargs['did'] in self.manager.db_info else 0
|
||||
|
||||
# we will set template path for sql scripts
|
||||
self.template_path = 'index/sql/#{0}#'.format(self.manager.version)
|
||||
self.template_path = compile_template_path(
|
||||
'index/sql/',
|
||||
self.manager.server_type,
|
||||
self.manager.version
|
||||
)
|
||||
|
||||
# We need parent's name eg table name and schema name
|
||||
# when we create new index in update we can fetch it using
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import * as _ from 'underscore';
|
||||
|
||||
function isServerGreenPlum(tableModel) {
|
||||
return !_.isUndefined(tableModel.node_info) &&
|
||||
!_.isUndefined(tableModel.node_info.server) &&
|
||||
tableModel.node_info.server.server_type === 'gpdb';
|
||||
}
|
||||
|
||||
export function show_advanced_tab(tableModel) {
|
||||
if (isServerGreenPlum(tableModel)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2,10 +2,12 @@ define('pgadmin.node.table', [
|
||||
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
|
||||
'underscore.string', 'sources/pgadmin', 'pgadmin.browser',
|
||||
'pgadmin.alertifyjs', 'pgadmin.backform', 'pgadmin.backgrid',
|
||||
'pgadmin.tables.js/show_advanced_tab',
|
||||
'pgadmin.browser.collection', 'pgadmin.node.column',
|
||||
'pgadmin.node.constraints', 'pgadmin.browser.table.partition.utils',
|
||||
], function(
|
||||
gettext, url_for, $, _, S, pgAdmin, pgBrowser, Alertify, Backform, Backgrid
|
||||
gettext, url_for, $, _, S, pgAdmin, pgBrowser, Alertify, Backform, Backgrid,
|
||||
ShowAdvancedTab
|
||||
) {
|
||||
|
||||
if (!pgBrowser.Nodes['coll-table']) {
|
||||
@@ -501,12 +503,15 @@ define('pgadmin.node.table', [
|
||||
return tbl_oid;
|
||||
},
|
||||
}),
|
||||
},{
|
||||
}, {
|
||||
id: 'advanced', label: gettext('Advanced'), type: 'group',
|
||||
visible: ShowAdvancedTab.show_advanced_tab,
|
||||
}, {
|
||||
id: 'coll_inherits', label: gettext('Inherited from table(s)'),
|
||||
type: 'text', group: gettext('Advanced'), mode: ['properties'],
|
||||
type: 'text', group: 'advanced', mode: ['properties'],
|
||||
},{
|
||||
id: 'inherited_tables_cnt', label: gettext('Inherited tables count'),
|
||||
type: 'text', mode: ['properties'], group: gettext('Advanced'),
|
||||
type: 'text', mode: ['properties'], group: 'advanced',
|
||||
disabled: 'inSchema',
|
||||
},{
|
||||
// Tab control for columns
|
||||
@@ -749,7 +754,7 @@ define('pgadmin.node.table', [
|
||||
},{
|
||||
id: 'typname', label: gettext('Of type'), type: 'text',
|
||||
mode: ['properties', 'create', 'edit'],
|
||||
disabled: 'checkOfType', url: 'get_oftype', group: gettext('Advanced'),
|
||||
disabled: 'checkOfType', url: 'get_oftype', group: 'advanced',
|
||||
deps: ['coll_inherits'], transform: function(data, cell) {
|
||||
var control = cell || this,
|
||||
m = control.model;
|
||||
@@ -802,27 +807,27 @@ define('pgadmin.node.table', [
|
||||
},{
|
||||
id: 'fillfactor', label: gettext('Fill factor'), type: 'int',
|
||||
mode: ['create', 'edit'], min: 10, max: 100,
|
||||
disabled: 'inSchema',group: gettext('Advanced'),
|
||||
disabled: 'inSchema',group: 'advanced',
|
||||
},{
|
||||
id: 'relhasoids', label: gettext('Has OIDs?'), cell: 'switch',
|
||||
type: 'switch', mode: ['properties', 'create', 'edit'],
|
||||
disabled: 'inSchema', group: gettext('Advanced'),
|
||||
disabled: 'inSchema', group: 'advanced',
|
||||
},{
|
||||
id: 'relpersistence', label: gettext('Unlogged?'), cell: 'switch',
|
||||
type: 'switch', mode: ['properties', 'create', 'edit'],
|
||||
disabled: 'inSchemaWithModelCheck',
|
||||
group: gettext('Advanced'),
|
||||
group: 'advanced',
|
||||
},{
|
||||
id: 'conname', label: gettext('Primary key'), cell: 'string',
|
||||
type: 'text', mode: ['properties'], group: gettext('Advanced'),
|
||||
type: 'text', mode: ['properties'], group: 'advanced',
|
||||
disabled: 'inSchema',
|
||||
},{
|
||||
id: 'reltuples', label: gettext('Rows (estimated)'), cell: 'string',
|
||||
type: 'text', mode: ['properties'], group: gettext('Advanced'),
|
||||
type: 'text', mode: ['properties'], group: 'advanced',
|
||||
disabled: 'inSchema',
|
||||
},{
|
||||
id: 'rows_cnt', label: gettext('Rows (counted)'), cell: 'string',
|
||||
type: 'text', mode: ['properties'], group: gettext('Advanced'),
|
||||
type: 'text', mode: ['properties'], group: 'advanced',
|
||||
disabled: 'inSchema', control: Backform.InputControl.extend({
|
||||
formatter: {
|
||||
fromRaw: function (rawData) {
|
||||
@@ -844,7 +849,7 @@ define('pgadmin.node.table', [
|
||||
}),
|
||||
},{
|
||||
id: 'relhassubclass', label: gettext('Inherits tables?'), cell: 'switch',
|
||||
type: 'switch', mode: ['properties'], group: gettext('Advanced'),
|
||||
type: 'switch', mode: ['properties'], group: 'advanced',
|
||||
disabled: 'inSchema',
|
||||
},{
|
||||
id: 'is_sys_table', label: gettext('System table?'), cell: 'switch',
|
||||
@@ -852,7 +857,7 @@ define('pgadmin.node.table', [
|
||||
disabled: 'inSchema',
|
||||
},{
|
||||
type: 'nested', control: 'fieldset', label: gettext('Like'),
|
||||
group: gettext('Advanced'),
|
||||
group: 'advanced',
|
||||
schema:[{
|
||||
id: 'like_relation', label: gettext('Relation'),
|
||||
type: 'text', mode: ['create', 'edit'], deps: ['typname'],
|
||||
@@ -1122,7 +1127,7 @@ define('pgadmin.node.table', [
|
||||
group: 'security', canDelete: true, control: 'unique-col-collection',
|
||||
},{
|
||||
id: 'vacuum_settings_str', label: gettext('Storage settings'),
|
||||
type: 'multiline', group: gettext('Advanced'), mode: ['properties'],
|
||||
type: 'multiline', group: 'advanced', mode: ['properties'],
|
||||
}],
|
||||
validate: function() {
|
||||
var msg,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
SELECT 'pg_catalog.' || quote_ident(collate_setting.value) AS copy_collation
|
||||
FROM (
|
||||
SELECT setting AS value
|
||||
FROM pg_settings
|
||||
WHERE name='lc_collate'
|
||||
) collate_setting;
|
||||
@@ -0,0 +1,6 @@
|
||||
SELECT 'pg_catalog.' || quote_ident(collate_setting.value) AS copy_collation
|
||||
FROM (
|
||||
SELECT setting AS value
|
||||
FROM pg_settings
|
||||
WHERE name='lc_collate'
|
||||
) collate_setting
|
||||
@@ -92,10 +92,13 @@ TABLESPACE {{ conn|qtIdent(data.spcname) }}
|
||||
{### SQL for Distribution ###}
|
||||
{% if data.distribution %}
|
||||
DISTRIBUTED BY ({% for attrnum in data.distribution %}{% if loop.index != 1 %}, {% endif %}{{ data.columns[attrnum-1].name }}{% endfor %})
|
||||
{% elif data.primary_key|length > 0 %}
|
||||
DISTRIBUTED BY ({% for c in data.primary_key[0].columns%}{% if loop.index != 1 %}, {% endif %}{{conn|qtIdent(c.column)}}{% endfor %})
|
||||
{% else %}
|
||||
DISTRIBUTED RANDOMLY
|
||||
{% endif %}
|
||||
{% if data.is_partitioned %} PARTITION BY {{ data.partition_scheme }}; {% endif %}
|
||||
;
|
||||
|
||||
{### Alter SQL for Owner ###}
|
||||
{% if data.relowner %}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from flask import Flask, render_template
|
||||
from jinja2 import FileSystemLoader, ChoiceLoader
|
||||
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
from pgadmin import VersionedTemplateLoader
|
||||
from pgadmin.utils.driver import get_driver
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
|
||||
|
||||
class TestTemplateCreate(BaseTestGenerator):
|
||||
scenarios = [
|
||||
(
|
||||
'When rendering GreenPlum 5.3 template, '
|
||||
'when no distribution is present, '
|
||||
'when no primary key is present, '
|
||||
'it returns "DISTRIBUTED RANDOMLY"',
|
||||
dict(
|
||||
template_path=os.path.join('table', 'sql', 'gpdb_5.0_plus', 'create.sql'),
|
||||
input_parameters=dict(
|
||||
data=dict()
|
||||
),
|
||||
expected_in_return_value='DISTRIBUTED RANDOMLY',
|
||||
expected_not_in_return_value='DISTRIBUTED BY '
|
||||
)
|
||||
),
|
||||
(
|
||||
'When rendering GreenPlum 5.3 template, '
|
||||
'when no distribution is present, '
|
||||
'when primary key is present, '
|
||||
'it returns "DISTRIBUTED BY (attr_primary_key)"',
|
||||
dict(
|
||||
template_path=os.path.join('table', 'sql', 'gpdb_5.0_plus', 'create.sql'),
|
||||
input_parameters=dict(
|
||||
data=dict(
|
||||
primary_key=[
|
||||
dict(
|
||||
columns=[dict(
|
||||
column='attr_primary_key_column_1'
|
||||
), dict(
|
||||
column='attr_primary_key_column_2'
|
||||
)]
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
expected_in_return_value='DISTRIBUTED BY (attr_primary_key_column_1, attr_primary_key_column_2)',
|
||||
expected_not_in_return_value='DISTRIBUTED RANDOMLY'
|
||||
)
|
||||
),
|
||||
(
|
||||
'When rendering GreenPlum 5.3 template, '
|
||||
'when distribution is present, '
|
||||
'it returns "DISTRIBUTED BY (attr1, attr2, attr4)"',
|
||||
dict(
|
||||
template_path=os.path.join('table', 'sql', 'gpdb_5.0_plus', 'create.sql'),
|
||||
input_parameters=dict(
|
||||
data=dict(
|
||||
distribution=[1, 2, 4],
|
||||
columns=[
|
||||
{'name': 'attr1'},
|
||||
{'name': 'attr2'},
|
||||
{'name': 'attr3'},
|
||||
{'name': 'attr4'},
|
||||
{'name': 'attr5'},
|
||||
]
|
||||
)
|
||||
),
|
||||
expected_in_return_value='DISTRIBUTED BY (attr1, attr2, attr4)',
|
||||
expected_not_in_return_value='DISTRIBUTED RANDOMLY'
|
||||
)
|
||||
),
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
self.loader = VersionedTemplateLoader(FakeApp())
|
||||
|
||||
def runTest(self):
|
||||
with FakeApp().app_context():
|
||||
result = render_template(self.template_path, **self.input_parameters)
|
||||
result_beautified = re.sub(' +', ' ', str(result).replace("\n", " ").strip())
|
||||
if hasattr(self, 'expected_return_value'):
|
||||
self.assertEqual(result_beautified, self.expected_return_value)
|
||||
if hasattr(self, 'expected_in_return_value'):
|
||||
self.assertIn(self.expected_in_return_value, result_beautified)
|
||||
if hasattr(self, 'expected_not_in_return_value'):
|
||||
self.assertNotIn(self.expected_not_in_return_value, result_beautified)
|
||||
|
||||
|
||||
class FakeApp(Flask):
|
||||
def __init__(self):
|
||||
super(FakeApp, self).__init__('')
|
||||
driver = get_driver(PG_DEFAULT_DRIVER, self)
|
||||
self.jinja_env.filters['qtLiteral'] = driver.qtLiteral
|
||||
self.jinja_env.filters['qtIdent'] = driver.qtIdent
|
||||
self.jinja_env.filters['qtTypeIdent'] = driver.qtTypeIdent
|
||||
self.jinja_loader = ChoiceLoader([
|
||||
FileSystemLoader(
|
||||
os.path.dirname(os.path.realpath(__file__)) + '/../templates/'
|
||||
),
|
||||
FileSystemLoader(
|
||||
os.path.dirname(os.path.realpath(__file__)) + '/../../templates/'
|
||||
),
|
||||
FileSystemLoader(
|
||||
os.path.dirname(os.path.realpath(__file__)) + '/../../types/templates/'
|
||||
),
|
||||
FileSystemLoader(
|
||||
os.path.dirname(os.path.realpath(__file__)) + '/../../../../templates/'
|
||||
),
|
||||
]
|
||||
)
|
||||
@@ -15,14 +15,14 @@ FROM
|
||||
(NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
|
||||
AND
|
||||
{{ condition }}
|
||||
AND (
|
||||
typnamespace = {{ schema_oid }}::oid
|
||||
OR nsp.nspname = 'pg_catalog'
|
||||
)
|
||||
{% if add_serials %}
|
||||
{# Here we will add serials types manually #}
|
||||
UNION SELECT 'smallserial', 0, 2, 'b', 0, 'pg_catalog', false, false
|
||||
UNION SELECT 'bigserial', 0, 8, 'b', 0, 'pg_catalog', false, false
|
||||
UNION SELECT 'serial', 0, 4, 'b', 0, 'pg_catalog', false, false
|
||||
{% endif %}
|
||||
AND (
|
||||
typnamespace = {{schema_oid}}::oid
|
||||
OR nsp.nspname = 'pg_catalog'
|
||||
)) AS dummy
|
||||
{% endif %}) AS dummy
|
||||
ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
SELECT 'pg_catalog.' || quote_ident(collate_setting.value) AS copy_collation
|
||||
FROM (
|
||||
SELECT setting AS value
|
||||
FROM pg_settings
|
||||
WHERE name='lc_collate'
|
||||
) collate_setting;
|
||||
Reference in New Issue
Block a user