Compare commits

...
99 Commits
Author SHA1 Message Date
Akshay Joshi 7b050a4c31 Update version for release. 2021-07-12 16:35:25 +05:30
Akshay Joshi 96085213fe Update Dependencies. 2021-07-12 16:26:00 +05:30
Domenico Sgarbossa 2ce2b457bf Update Italian translation. 2021-07-12 14:12:12 +05:30
Identifier Anonymous a2171aa27b Update Japanese translation. 2021-07-12 14:10:22 +05:30
Libor M ea3d71c0df Update Czech translation. 2021-07-12 14:08:58 +05:30
Akshay Joshi b154be24ec Update message catalog. 2021-07-09 21:53:33 +05:30
Khushboo Vashi 3590c9172c Fixed an issue where the user unable to login with OAuth2 when LDAP & OAuth2 configured as login sources. Fixes #6594 2021-07-09 21:50:50 +05:30
Khushboo Vashi e981868246 Fixed an issue where the user unable to add server in Kerberos Authentication Mode with Master Password. Fixes #6595 2021-07-09 21:47:34 +05:30
Khushboo Vashi 5ee8045916 Informative error should be shown if Oauth2 profile does not have email id registered. Fixes #6590 2021-07-07 17:58:49 +05:30
Khushboo Vashi 36086722b3 RESQL testcase fixes for Triggers. 2021-07-07 17:56:30 +05:30
Rahul Shirsat 8edd5946e5 1) Modified some labels and controls.
2) Fixed issue where the same user is showing in SQL query.

3) Added SQL tab in the dialog.

refs #3893
2021-07-07 10:44:02 +05:30
Akshay Joshi a0b2a28ee2 1) Set the default value of the long-running threshold to 2 minutes for warning and 5 minutes for the alert.
2) Use $color-danger for the alert threshold.
2021-07-06 19:52:37 +05:30
Identifier Anonymous 39a845ad31 Remove extra brackets in CREATE script and DDL comparison for trigger node. 2021-07-06 19:07:35 +05:30
Nikhil Mohite 669bdc7e38 Resolved the issue when the user selects the folder 'Select' button is not getting enabled for 'Select folder' dialog.
refs #6536
2021-07-06 19:00:08 +05:30
Pradip Parkale 5d4c073730 Fixed an issue where Schema Diff and Debugger give a blank white panel.
refs #6398
2021-07-06 18:56:21 +05:30
Khushboo Vashi 48ca83f31d Added support for OAuth 2 authentication. Fixes #5940
Initial patch sent by: Florian Sabonchi
2021-07-06 13:22:58 +05:30
Dave Page fff4060b31 Don't use fuzzy matching when updating message catalogs, to avoid issues where the number string substitution placeholders changes, per discussion. 2021-07-05 09:49:56 +01:00
Rahul Shirsat 9fdda038a9 Resolve the log in issue for a user having a non-existing email id
1) Added CHECK_EMAIL_DELIVERABILITY & SECURITY_EMAIL_VALIDATOR_ARGS.
  2) Added test cases for deliverability check.

Fixes #6550
2021-07-05 12:55:40 +05:30
Akshay Joshi ef67409d61 Highlighted long running queries on the dashboards. Fixes #1975 2021-07-01 18:10:55 +05:30
Dave Page d90472014d Remove leading whitespace and replace it with '[...] ' in the Query Tool data grid so cells don't look empty.
Fixes #6427
2021-07-01 09:17:35 +01:00
Dave Page a2b67b933e PEP-8 fix. 2021-06-30 11:04:50 +01:00
Dave Page b98e881d84 Disable email deliverability check that was introduced in flask-security-too by default to maintain backwards compatibility.
Fixes #6550
2021-06-30 10:46:32 +01:00
Dave Page e978621597 Fix typo in filename. 2021-06-28 15:23:18 +01:00
Rahul Shirsat 5fe52b9cfe Added support for Reassign/Drop Owned for login roles. Fixes #3893 2021-06-28 18:55:52 +05:30
Nikhil Mohite 5c6d00d545 Fixed directory selection issue with the folder dialog. Fixes #6536 2021-06-28 18:55:52 +05:30
Dave Page 6429a5b31a Clarify when container config envvars may be ignored. 2021-06-28 09:48:24 +01:00
Akshay Joshi e68c8305a2 Added option to provide maximum width of the column when 'Resize by data?’ option in the preferences is set to True. Fixes #6559 2021-06-28 11:51:21 +05:30
Pradip Parkale e095d382b3 Fixed an issue where incorrect column name listed in the properties of Index. Fixes #6557 2021-06-27 19:00:16 +05:30
Akshay Joshi 25ada15546 Temporary comment the logic to check API test cases are fixed for EPAS/PG 9.6 2021-06-25 19:40:52 +05:30
Pradip Parkale 5581f0909a Fixed an issue where Debugger and ERD tool panel give a blank white panel, missing from the last patch.
refs #6398
2021-06-25 11:38:02 +05:30
Pradip Parkale 462b86df8d Remove some configuration from the about dialog. 2021-06-25 11:11:28 +05:30
Nikhil Mohite 6645625e6b Fixed copy/paste issues for PSQL tool terminal. Fixes #6547. 2021-06-24 20:00:52 +05:30
Ashesh Vashi cfb68d73a0 Fixed server mode api test case failure. 2021-06-24 19:41:58 +05:30
Ashesh Vashi 9574f43f87 Refactor the registry class logic and remove duplicate code for the same functionality. 2021-06-24 11:30:11 +05:30
Akshay Joshi a53be65ab0 Fixed Czech translation string for 'Login' keyword. Fixes #6555
Patch sent by: Waclaw
2021-06-24 11:19:26 +05:30
Libor M cc989c5c08 Added missing gettexts and text space improvements. 2021-06-24 11:15:50 +05:30
Nikhil Mohite 313224e6f5 Ensure that Data Output panel can be snapped back after it is detached. Fixes #4189 2021-06-23 15:06:06 +05:30
Nikhil Mohite 2adb29ffc0 Fixed an issue where the New Connection Drop Down has lost default maintenance database, auto-select, and tab-through functionality. Fixes #6505 2021-06-23 12:48:17 +05:30
Pradip Parkale 80ccd62d38 Fixed an issue in the search object when searching in 'all types' or 'subscription' if the user doesn't have access to the subscription. Fixes #6448 2021-06-23 12:39:55 +05:30
Aditya Toshniwal b81ff45d34 Fixed replace keyboard shortcut issue in the query tool on the normal keyboard layout. Fixes #6388 2021-06-23 12:34:01 +05:30
Aditya Toshniwal 81b78dd2b2 Do not block the query editor window when running a query. Fixes #3920 2021-06-23 12:22:24 +05:30
Nikhil Mohite e2302a6c9b Ensure that setting 'Open in new browser tab' should be visible, it should not be based on the value of 'ENABLE_PSQL'. Fixes #6541 2021-06-23 11:59:56 +05:30
Yogesh Mahajan 2486b79450 Fixed feature tests failure issue due to binary path feature. 2021-06-23 11:55:27 +05:30
Pradip Parkale 0b52ef6eb0 Fixed an issue where detaching the query editor panel gives a blank white panel. Fixes #6398 2021-06-23 11:49:40 +05:30
Nikhil Mohite a533620684 Fixed an issue where Execute/Refresh button should not be disabled when we run the empty query. Fixes #6489 2021-06-23 11:49:40 +05:30
Dave Page 09d8d0f362 Fix path on windows. Fixes #6558 2021-06-23 07:04:59 +01:00
Dave Page 4e067835c3 Revert "Fixed API test cases for PG/EPAS 9.6" per Khushboo.
This reverts commit 37278f2cd3.
2021-06-17 13:27:33 +01:00
Khushboo Vashi 37278f2cd3 Fixed API test cases for PG/EPAS 9.6 2021-06-17 16:22:53 +05:30
Akshay Joshi 16d2a3096a 1) Fixed an issue where the binary path is not correctly parsed for version 9.6. Fixes #6534
2) Added the default binary path in the container. 
3) Fixed the typo in the documentation.
2021-06-15 19:49:46 +05:30
Dave Page 083509eb97 Show the full range of options for the default binary path dict. 2021-06-15 14:32:05 +01:00
Dave Page 0c154deeec Fix dict definition. 2021-06-15 14:19:31 +01:00
Akshay Joshi 082c9707c0 Fixed documentation issue 'Definition list ends without a blank line; unexpected unindent.' 2021-06-15 16:45:16 +05:30
Akshay Joshi 15798ee168 Updated DEFAULT_BINARY_PATHS for container. 2021-06-15 16:08:15 +05:30
Dave Page e37b7eae3f Cleanup psql docs. 2021-06-15 11:09:52 +01:00
Akshay Joshi ae2d588f46 Update version for release. 2021-06-14 21:00:26 +05:30
Akshay Joshi 12d93d0805 Update DEPENDENCIES. 2021-06-14 20:59:05 +05:30
Nikhil Mohite 2549688bdf 1) Disable the PSQL feature entirely in server mode by default.
2) Remove the code that attempts to filter out commands.

refs #2341
2021-06-14 20:53:11 +05:30
Akshay Joshi c2ed799113 If the binary path contains '' then show as it is on GUI if the path contains valid utilities. 2021-06-14 19:23:26 +05:30
Nikhil Mohite 71526ac79f Ensure that the calendar control should be disabled in the properties panel for Role. Fixes #6469. 2021-06-14 16:59:04 +05:30
Pradip Parkale 3d685ef96c Updated variable name as per review comments. 2021-06-14 16:42:27 +05:30
Akshay Joshi 2fdde6218a Fixed binary path issue on Windows platform. refs #5370 2021-06-14 15:01:49 +05:30
Nikhil Mohite 09693d14d1 Added check if the Windows version is not supporting the ConPty or WinPty disable the PSQL for that version.
refs #2341
2021-06-14 11:47:40 +05:30
Fred Escallier dcaeb20e29 Update French translation. 2021-06-14 11:47:40 +05:30
fn ln d93ec3bb91 Update Japanese translation. 2021-06-14 11:47:40 +05:30
Libor M f29852f6f0 Update Czech translation. 2021-06-14 11:47:40 +05:30
Domenico Sgarbossa 7d5fc84747 Update Italian translation. 2021-06-14 11:47:40 +05:30
Dave Page 4a3a5174b2 Disable browser password saving in the runtime. Fixes #6473 2021-06-11 15:10:38 +01:00
Pradip Parkale e0d094b2aa Fixed issues related to About dialog:
1) On resizing, the server configuration text area should be resized.
2) Any password should not be visible in the configuration.
3) Configurations are not properly quoted.
4) Added the "Copy" button so that the user can copy the configuration directly.

refs #6231
2021-06-11 19:30:32 +05:30
Pradip Parkale e3190b86ab Fixed an issue where a decimal number is appended for character varying fields while downloading the data in CSV format. Fixes #6520 2021-06-11 19:29:20 +05:30
Akshay Joshi b9b0a573e5 Update message catalogs. 2021-06-11 19:17:40 +05:30
Akshay Joshi 0dbfbd8dfc 1) Fixed Selenoid test cases.
2) Fixed RESQL test case failing on Jenkins.
2021-06-11 15:34:12 +05:30
Aditya Toshniwal 6e42d9113b Fixed user password-related issues.
refs #6225
2021-06-10 22:56:38 +05:30
Khushboo Vashi 460fb7ec29 Fixed an issue where pgAdmin does not open after password reset in server mode. Fixes #6513 2021-06-10 22:55:31 +05:30
Akshay Joshi c86a2b643a 1) Binary path set to the default location in which we install the binaries.
2) Validate path not working if there is a space in the binary path.
3) Handle the case when the path contains '$DIR'. 

refs #5370
2021-06-10 22:49:05 +05:30
Yogesh Mahajan b2042f48cd Added RESQL/MSQL test cases for Table and its child nodes. Fixes #4622 2021-06-09 18:16:50 +05:30
Dave Page d276f37e87 Support non-admin installation on Windows. Fixes #6524 2021-06-09 13:32:48 +01:00
Nikhil Mohite 7c88ee7cff Added a mechanism to detect a corrupt/broken config database file. Fixes #6460 2021-06-08 19:41:47 +05:30
Nikhil Mohite 93ddc4a5ba Ensure that the user should be able to add members in Login/Role group while creating it. Fixes #6466 2021-06-08 19:33:03 +05:30
Nikhil Mohite 9f12747d9b Added PSQL tool support for the Windows platform.
Fixed following issues:
1. If the database name contains escape characters then PSQL unable to connect.
2. If the user terminates the connection by typing the 'exit' command, PSQL
   will show the connection termination msg.

Fixes #2341
2021-06-08 14:58:43 +05:30
Akshay Joshi 5a086a9173 Fixed API test cases failed due to wrong handling of default binary path. 2021-06-08 13:24:17 +05:30
Nikhil Mohite e1067ffe67 Ensure that the Query Tool connection string should not be changed as per the 'Query Tool tab title'. Fixes #6404 2021-06-07 22:07:51 +05:30
Rahul Shirsat d5f537aae4 Added extra check for verifying the rename of the database.
refs #4203
2021-06-07 21:11:28 +05:30
Nikhil Mohite 5b12483416 Fixed an issue where the Foreground Color property of server dialog does not work. Fixes #6482 2021-06-07 21:09:04 +05:30
Akshay Joshi 07eb541806 1) Added logic to set the appropriate default binary path if DEFAULT_BINARY_PATH is
set in the config and the user not updated the preferences.
2) Remove 'gpdb' from DEFAULT_BINARY_PATH.
3) Fixed API test cases. 

refs #5370
2021-06-07 20:36:34 +05:30
Aditya Toshniwal 065a3aa2f5 Updated Flask-Security-Too to the latest v4. Fixes #6225 2021-06-06 13:58:06 +05:30
Akshay Joshi 2aa2d79de2 Fixed Jenkins build, added 'user-agents' in requirements.txt which was missing in the last patch. 2021-06-04 18:49:19 +05:30
Pradip Parkale a0deab901d Fixed OS detail issue for Linux and MacOS Big Sur. Fixes #6231. 2021-06-04 17:57:58 +05:30
Akshay Joshi 4bc4ca1ba9 1) Added browse button to select the binary path in the Preferences. Fixes #1561
2) Added support to set the binary path for the different database server versions. Fixes #5370
2021-06-04 17:55:35 +05:30
Rahul Shirsat ac8e8961ce Added Grant Wizard option under Package node. Fixes #1591 2021-06-04 12:47:37 +05:30
Pradip Parkale 2c51925638 Added OS, Browser, Configuration details in the About dialog. Fixes #6231 2021-06-01 20:18:24 +05:30
Nikhil Mohite e0eac875b6 Disable the PSQL tool for Windows, the 'fcntl' module is not working on Windows. 2021-06-01 20:04:43 +05:30
Rahul Shirsat 9ac08c263b Fixed duplicate SQL issue for tables with more than one partition. Fixes #6478 2021-05-31 12:46:07 +05:30
Rahul Shirsat 658a2de619 Fixed the issue of renaming the database by another user. Fixes #4203 2021-05-31 12:41:09 +05:30
Ashesh Vashi a487a51135 Fixes SonarQube issues. 2021-05-29 12:55:59 +05:30
Yogesh Mahajan 2d58f60a53 Modifies the way to execute feature tests in parallel and it should be configured in Server Mode. 2021-05-27 11:01:25 +05:30
Yogesh Mahajan faa49687be Added support to rotate the pgadmin log file on the basis of Size and Age. Fixes #6395 2021-05-25 20:18:46 +05:30
Nikhil Mohite 3ddf941cd7 Added support to launch PSQL for the connected database server. Fixes #2341 2021-05-25 20:12:57 +05:30
Rahul Shirsat 37dece2cd8 Added window maximize/restore functionality for properties dialog. Fixes #4064 2021-05-24 22:08:23 +05:30
Dave Page 1ead82f9b8 Various fixes to the setup process description. 2021-05-24 17:03:42 +01:00
696 changed files with 51231 additions and 17694 deletions

No files matched your search

+88 -69
View File
@@ -23,19 +23,18 @@ Python Dependencies
Name Version Licence URL
---- ------- ------- ---
cheroot 8.5.2 UNKNOWN https://cheroot.cherrypy.org
Flask 1.1.2 BSD-3-Clause https://palletsprojects.com/p/flask/
Flask 1.1.4 BSD-3-Clause https://palletsprojects.com/p/flask/
Flask-Gravatar 0.5.0 BSD https://github.com/zzzsochi/Flask-Gravatar/
Flask-Login 0.5.0 MIT https://github.com/maxcountryman/flask-login
Flask-Mail 0.9.1 BSD https://github.com/rduplain/flask-mail
Flask-Migrate 2.6.0 MIT http://github.com/miguelgrinberg/flask-migrate/
Flask-SQLAlchemy 2.4.4 BSD-3-Clause https://github.com/pallets/flask-sqlalchemy
Flask-Migrate 2.7.0 MIT http://github.com/miguelgrinberg/flask-migrate/
Flask-SQLAlchemy 2.5.1 BSD-3-Clause https://github.com/pallets/flask-sqlalchemy
Flask-WTF 0.14.3 BSD https://github.com/lepture/flask-wtf
Flask-Compress 1.8.0 MIT https://github.com/colour-science/flask-compress
Flask-Compress 1.9.0 MIT https://github.com/colour-science/flask-compress
passlib 1.7.4 BSD https://passlib.readthedocs.io
pytz 2021.1 MIT http://pythonhosted.org/pytz
simplejson 3.17.2 MIT License https://github.com/simplejson/simplejson
six 1.15.0 MIT https://github.com/benjaminp/six
six 1.16.0 MIT https://github.com/benjaminp/six
speaklater3 1.4 UNKNOWN https://github.com/ThomasWaldmann/speaklater
sqlparse 0.4.1 BSD-3-Clause https://github.com/andialbrecht/sqlparse
WTForms 2.3.3 BSD-3-Clause https://wtforms.readthedocs.io/
@@ -43,16 +42,27 @@ Flask-Paranoid 0.2.0
psutil 5.8.0 BSD https://github.com/giampaolo/psutil
psycopg2 2.8.6 LGPL with exceptions https://psycopg.org/
python-dateutil 2.8.1 Dual License https://dateutil.readthedocs.io
SQLAlchemy 1.3.23 MIT http://www.sqlalchemy.org
Flask-Security-Too 3.4.5 MIT https://github.com/Flask-Middleware/flask-security
SQLAlchemy 1.3.24 MIT http://www.sqlalchemy.org
itsdangerous 1.1.0 BSD https://palletsprojects.com/p/itsdangerous/
Flask-Security-Too 4.0.1 MIT https://github.com/Flask-Middleware/flask-security
bcrypt 3.2.0 Apache License, Version 2.0 https://github.com/pyca/bcrypt/
cryptography 3.3.1 BSD or Apache License, Version 2.0 https://github.com/pyca/cryptography
cryptography 3.4.7 BSD or Apache License, Version 2.0 https://github.com/pyca/cryptography
sshtunnel 0.4.0 MIT https://github.com/pahaz/sshtunnel
ldap3 2.9 LGPL v3 https://github.com/cannatag/ldap3
Flask-BabelEx 0.9.4 BSD http://github.com/mrjoes/flask-babelex
gssapi 1.6.12 LICENSE.txt https://github.com/pythongssapi/python-gssapi
Flask-SocketIO 5.0.3 MIT http://github.com/miguelgrinberg/Flask-SocketIO/
eventlet 0.31.0 UNKNOWN http://eventlet.net
httpagentparser 1.9.1 http://www.opensource.org/licenses/mit-license.php http://shon.github.com/httpagentparser
user-agents 2.2.0 MIT https://github.com/selwin/python-user-agents
pywinpty 1.1.1 Unknown Unknown
Authlib 0.15.4 BSD-3-Clause https://authlib.org/
requests 2.25.1 Apache 2.0 https://requests.readthedocs.io
28 dependencies listed.
NOTE: This report was generated using Python 3.9. Full information may not be
shown for Python modules that are not required with this version.
35 dependencies listed.
Javascript Dependencies
=======================
@@ -61,11 +71,11 @@ Name Version
---- ------- ------- ---
@babel/code-frame 7.12.13 MIT https://github.com/babel/babel.git
@babel/compat-data 7.14.0 MIT https://github.com/babel/babel.git
@babel/core 7.14.2 MIT https://github.com/babel/babel.git
@babel/generator 7.14.2 MIT https://github.com/babel/babel.git
@babel/core 7.14.3 MIT https://github.com/babel/babel.git
@babel/generator 7.14.3 MIT https://github.com/babel/babel.git
@babel/helper-annotate-as-pure 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-compilation-targets 7.13.16 MIT https://github.com/babel/babel.git
@babel/helper-create-class-features-plugin 7.14.2 MIT https://github.com/babel/babel.git
@babel/helper-create-class-features-plugin 7.14.3 MIT https://github.com/babel/babel.git
@babel/helper-function-name 7.14.2 MIT https://github.com/babel/babel.git
@babel/helper-get-function-arity 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-member-expression-to-functions 7.13.12 MIT https://github.com/babel/babel.git
@@ -73,18 +83,18 @@ Name Version
@babel/helper-module-transforms 7.14.2 MIT https://github.com/babel/babel.git
@babel/helper-optimise-call-expression 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-plugin-utils 7.13.0 MIT https://github.com/babel/babel.git
@babel/helper-replace-supers 7.13.12 MIT https://github.com/babel/babel.git
@babel/helper-replace-supers 7.14.3 MIT https://github.com/babel/babel.git
@babel/helper-simple-access 7.13.12 MIT https://github.com/babel/babel.git
@babel/helper-split-export-declaration 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-validator-identifier 7.14.0 MIT https://github.com/babel/babel.git
@babel/helper-validator-option 7.12.17 MIT https://github.com/babel/babel.git
@babel/helpers 7.14.0 MIT https://github.com/babel/babel.git
@babel/highlight 7.14.0 MIT https://github.com/babel/babel.git
@babel/parser 7.14.2 MIT https://github.com/babel/babel.git
@babel/parser 7.14.3 MIT https://github.com/babel/babel.git
@babel/plugin-proposal-class-properties 7.13.0 MIT https://github.com/babel/babel.git
@babel/plugin-syntax-jsx 7.12.13 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-display-name 7.14.2 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-jsx 7.13.12 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-jsx 7.14.3 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-jsx-development 7.12.17 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-pure-annotations 7.12.1 MIT https://github.com/babel/babel.git
@babel/preset-react 7.13.13 MIT https://github.com/babel/babel.git
@@ -101,8 +111,9 @@ Name Version
@projectstorm/react-diagrams-routing 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
@simonwep/pickr 1.8.1 MIT https://github.com/Simonwep/pickr.git
@tippyjs/react 4.2.5 MIT git+https://github.com/atomiks/tippyjs-react.git
@types/component-emitter 1.2.10 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
@types/json-schema 7.0.7 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
@types/node 15.0.3 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
@types/node 15.6.1 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
@types/parse-json 4.0.0 MIT https://www.github.com/DefinitelyTyped/DefinitelyTyped.git
acitree 4.5.0-rc.7 MIT https://github.com/imsurinder90/jquery-aciTree.git
ajv 6.12.6 MIT https://github.com/ajv-validator/ajv.git
@@ -131,8 +142,10 @@ backform 0.2.0
backgrid 0.3.8 MIT http://github.com/cloudflare/backgrid
backgrid-filter 0.3.7 MIT git://github.com/wyuenho/backgrid-text-cell.git
backgrid-select-all 0.3.5 MIT git://github.com/wyuenho/backgrid-select-all.git
backo2 1.0.2 MIT https://github.com/mokesmokes/backo.git
balanced-match 1.0.2 MIT git://github.com/juliangruber/balanced-match.git
base64-arraybuffer 0.2.0 MIT https://github.com/niklasvh/base64-arraybuffer
base64-arraybuffer 0.1.4 MIT https://github.com/niklasvh/base64-arraybuffer
big.js 5.2.2 MIT https://github.com/MikeMcl/big.js.git
bignumber.js 9.0.1 MIT https://github.com/MikeMcl/bignumber.js.git
bignumber.js 7.2.1 MIT https://github.com/MikeMcl/bignumber.js.git
@@ -141,7 +154,6 @@ bootstrap4-toggle 3.6.1
brace-expansion 1.1.11 MIT git://github.com/juliangruber/brace-expansion.git
browserslist 4.16.6 MIT https://github.com/browserslist/browserslist.git
callsites 3.1.0 MIT https://github.com/sindresorhus/callsites.git
camelcase 6.2.0 MIT https://github.com/sindresorhus/camelcase.git
caniuse-api 3.0.0 MIT https://github.com/nyalab/caniuse-api.git
chalk 2.4.2 MIT https://github.com/chalk/chalk.git
chalk 4.1.1 MIT https://github.com/chalk/chalk.git
@@ -151,38 +163,39 @@ chartjs-color 2.4.1
chartjs-color-string 0.6.0 MIT https://github.com/chartjs/chartjs-color-string.git
closest 0.0.1 MIT https://github.com/ForbesLindesay/closest.git
co 4.6.0 MIT https://github.com/tj/co.git
codemirror 5.61.0 MIT https://github.com/codemirror/CodeMirror.git
color 3.1.3 MIT https://github.com/Qix-/color.git
codemirror 5.61.1 MIT https://github.com/codemirror/CodeMirror.git
color-convert 1.9.3 MIT https://github.com/Qix-/color-convert.git
color-convert 2.0.1 MIT https://github.com/Qix-/color-convert.git
color-name 1.1.3 MIT git@github.com:dfcreative/color-name.git
color-name 1.1.4 MIT git@github.com:colorjs/color-name.git
color-string 1.5.5 MIT https://github.com/Qix-/color-string.git
colord 2.0.0 MIT https://github.com/omgovich/colord.git
colorette 1.2.2 MIT https://github.com/jorgebucaran/colorette.git
commander 7.2.0 MIT https://github.com/tj/commander.js.git
component-emitter 1.3.0 MIT https://github.com/component/emitter.git
concat-map 0.0.1 MIT git://github.com/substack/node-concat-map.git
convert-source-map 1.7.0 MIT git://github.com/thlorenz/convert-source-map.git
core-js 3.12.1 MIT https://github.com/zloirock/core-js.git
core-js 3.13.0 MIT https://github.com/zloirock/core-js.git
core-js 2.6.12 MIT https://github.com/zloirock/core-js.git
cosmiconfig 7.0.0 MIT git+https://github.com/davidtheclark/cosmiconfig.git
css-color-names 1.0.1 MIT git://github.com/bahamas10/css-color-names.git
css-color-names 0.0.4 MIT git://github.com/bahamas10/css-color-names.git
css-line-break 1.1.1 MIT git+ssh://git@github.com/niklasvh/css-line-break.git
css-loader 5.2.4 MIT https://github.com/webpack-contrib/css-loader.git
css-loader 5.2.6 MIT https://github.com/webpack-contrib/css-loader.git
css-tree 1.1.3 MIT https://github.com/csstree/csstree.git
cssesc 3.0.0 MIT https://github.com/mathiasbynens/cssesc.git
cssnano 5.0.2 MIT https://github.com/cssnano/cssnano.git
cssnano-preset-default 5.0.1 MIT https://github.com/cssnano/cssnano.git
cssnano-utils 2.0.0 MIT https://github.com/cssnano/cssnano.git
cssnano 5.0.4 MIT https://github.com/cssnano/cssnano.git
cssnano-preset-default 5.1.1 MIT https://github.com/cssnano/cssnano.git
cssnano-utils 2.0.1 MIT https://github.com/cssnano/cssnano.git
csso 4.2.0 MIT https://github.com/css/csso.git
dagre 0.8.5 MIT https://github.com/dagrejs/dagre.git
debug 4.3.1 MIT git://github.com/visionmedia/debug.git
debug 2.6.9 MIT git://github.com/visionmedia/debug.git
detect-indent 4.0.0 MIT https://github.com/sindresorhus/detect-indent.git
dom-serializer 1.3.1 MIT git://github.com/cheeriojs/dom-renderer.git
dot-prop 5.3.0 MIT https://github.com/sindresorhus/dot-prop.git
dom-serializer 1.3.2 MIT git://github.com/cheeriojs/dom-renderer.git
dropzone 5.9.2 MIT https://github.com/dropzone/dropzone.git
emojis-list 3.0.0 MIT git+https://github.com/kikobeats/emojis-list.git
engine.io-client 5.1.1 MIT https://github.com/socketio/engine.io-client.git
engine.io-parser 4.0.2 MIT git@github.com:socketio/engine.io-parser.git
error-ex 1.3.2 MIT https://github.com/qix-/node-error-ex.git
escalade 3.1.1 MIT https://github.com/lukeed/escalade.git
escape-string-regexp 1.0.5 MIT https://github.com/sindresorhus/escape-string-regexp.git
@@ -195,6 +208,7 @@ globals 11.12.0
globals 9.18.0 MIT https://github.com/sindresorhus/globals.git
graphlib 2.1.8 MIT https://github.com/dagrejs/graphlib.git
has-ansi 2.0.0 MIT https://github.com/sindresorhus/has-ansi.git
has-cors 1.1.0 MIT git://github.com/component/has-cors.git
has-flag 3.0.0 MIT https://github.com/sindresorhus/has-flag.git
has-flag 4.0.0 MIT https://github.com/sindresorhus/has-flag.git
hex-color-regex 1.1.0 MIT https://github.com/regexps/hex-color-regex.git
@@ -205,16 +219,13 @@ html2canvas 1.0.0-rc.7
immutability-helper 3.1.1 MIT git+https://github.com/kolodny/immutability-helper.git
import-fresh 3.3.0 MIT https://github.com/sindresorhus/import-fresh.git
imports-loader 2.0.0 MIT https://github.com/webpack-contrib/imports-loader.git
indexes-of 1.0.1 MIT git://github.com/dominictarr/indexes-of.git
invariant 2.2.4 MIT https://github.com/zertosh/invariant
ip-address 7.1.0 MIT git://github.com/beaugunderson/ip-address.git
is-absolute-url 3.0.3 MIT https://github.com/sindresorhus/is-absolute-url.git
is-any-array 1.0.0 MIT https://github.com/cheminfo-js/is-any-array.git
is-arrayish 0.2.1 MIT https://github.com/qix-/node-is-arrayish.git
is-arrayish 0.3.2 MIT https://github.com/qix-/node-is-arrayish.git
is-color-stop 1.1.0 MIT git+https://github.com/pigcan/is-color-stop.git
is-finite 1.1.0 MIT https://github.com/sindresorhus/is-finite.git
is-obj 2.0.0 MIT https://github.com/sindresorhus/is-obj.git
istanbul-instrumenter-loader 3.0.1 MIT https://github.com/webpack-contrib/istanbul-instrumenter-loader.git
jquery 3.6.0 MIT https://github.com/jquery/jquery.git
jquery-contextmenu 2.9.2 MIT git://github.com/swisnl/jQuery-contextMenu.git
@@ -253,46 +264,47 @@ ms 2.1.2
ms 2.0.0 MIT https://github.com/zeit/ms.git
nanoid 3.1.23 MIT https://github.com/ai/nanoid.git
nanopop 2.1.0 MIT https://github.com/Simonwep/nanopop.git
node-releases 1.1.71 MIT git+https://github.com/chicoxyzzy/node-releases.git
normalize-url 4.5.0 MIT https://github.com/sindresorhus/normalize-url.git
node-releases 1.1.72 MIT git+https://github.com/chicoxyzzy/node-releases.git
normalize-url 4.5.1 MIT https://github.com/sindresorhus/normalize-url.git
object-assign 4.1.1 MIT https://github.com/sindresorhus/object-assign.git
parent-module 1.0.1 MIT https://github.com/sindresorhus/parent-module.git
parse-json 5.2.0 MIT https://github.com/sindresorhus/parse-json.git
parseqs 0.0.6 MIT https://github.com/get/querystring.git
parseuri 0.0.6 MIT https://github.com/get/parseuri.git
path-type 4.0.0 MIT https://github.com/sindresorhus/path-type.git
pathfinding 0.4.18 MIT git://github.com/qiao/PathFinding.js.git
performance-now 2.1.0 MIT git://github.com/braveg1rl/performance-now.git
popper.js 1.16.1 MIT git+https://github.com/FezVrasta/popper.js.git
postcss 8.2.15 MIT https://github.com/postcss/postcss.git
postcss 8.3.0 MIT https://github.com/postcss/postcss.git
postcss-calc 8.0.0 MIT https://github.com/postcss/postcss-calc.git
postcss-colormin 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-convert-values 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-discard-comments 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-discard-duplicates 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-discard-empty 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-discard-overridden 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-merge-longhand 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-merge-rules 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-minify-font-values 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-minify-gradients 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-minify-params 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-minify-selectors 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-colormin 5.1.1 MIT https://github.com/cssnano/cssnano.git
postcss-convert-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-discard-comments 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-discard-duplicates 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-discard-empty 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-discard-overridden 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-merge-longhand 5.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-merge-rules 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-minify-font-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-minify-gradients 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-minify-params 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-minify-selectors 5.1.0 MIT https://github.com/cssnano/cssnano.git
postcss-modules-local-by-default 4.0.0 MIT https://github.com/css-modules/postcss-modules-local-by-default.git
postcss-normalize-charset 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-display-values 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-positions 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-repeat-style 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-string 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-timing-functions 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-unicode 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-url 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-whitespace 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-ordered-values 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-reduce-initial 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-reduce-transforms 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-charset 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-display-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-positions 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-repeat-style 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-string 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-timing-functions 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-unicode 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-url 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-whitespace 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-ordered-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-reduce-initial 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-reduce-transforms 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-selector-parser 6.0.6 MIT https://github.com/postcss/postcss-selector-parser.git
postcss-selector-parser 3.1.2 MIT https://github.com/postcss/postcss-selector-parser.git
postcss-svgo 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-unique-selectors 5.0.0 MIT https://github.com/cssnano/cssnano.git
postcss-svgo 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-unique-selectors 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-value-parser 4.1.0 MIT https://github.com/TrySound/postcss-value-parser.git
punycode 2.1.1 MIT https://github.com/bestiejs/punycode.js.git
raf 3.4.1 MIT git://github.com/chrisdickinson/raf.git
@@ -309,15 +321,16 @@ schema-utils 3.0.0
schema-utils 0.3.0 MIT git+https://github.com/webpack-contrib/schema-utils.git
select2 4.0.13 MIT git://github.com/select2/select2.git
shim-loader 1.0.1 MIT https://github.com/zinserjan/shim-loader
simple-swizzle 0.2.2 MIT https://github.com/qix-/node-simple-swizzle.git
slickgrid 2.3.16 MIT git+https://github.com/6pac/SlickGrid.git
snapsvg-cjs 0.0.6 MIT git+https://github.com/geelen/Snap.svg-cjs.git
socket.io-client 4.1.2 MIT https://github.com/socketio/socket.io-client.git
socket.io-parser 4.0.4 MIT https://github.com/socketio/socket.io-parser.git
source-list-map 1.1.2 MIT https://github.com/webpack/source-list-map.git
split.js 1.6.4 MIT https://github.com/nathancahill/split
stable 0.1.8 MIT https://github.com/Two-Screen/stable.git
strip-ansi 3.0.1 MIT https://github.com/chalk/strip-ansi.git
strip-comments 2.0.1 MIT https://github.com/jonschlinkert/strip-comments.git
stylehacks 5.0.0 MIT https://github.com/cssnano/cssnano.git
stylehacks 5.0.1 MIT https://github.com/cssnano/cssnano.git
supports-color 5.5.0 MIT https://github.com/chalk/supports-color.git
supports-color 7.2.0 MIT https://github.com/chalk/supports-color.git
supports-color 2.0.0 MIT https://github.com/chalk/supports-color.git
@@ -330,17 +343,22 @@ to-fast-properties 2.0.0
to-fast-properties 1.0.3 MIT https://github.com/sindresorhus/to-fast-properties.git
trim-right 1.0.1 MIT https://github.com/sindresorhus/trim-right.git
underscore 1.13.1 MIT git://github.com/jashkenas/underscore.git
uniq 1.0.1 MIT git://github.com/mikolalysenko/uniq.git
uniqs 2.0.0 MIT git://github.com/fgnass/uniqs.git
util-deprecate 1.0.2 MIT git://github.com/TooTallNate/util-deprecate.git
vendors 1.0.4 MIT https://github.com/wooorm/vendors.git
webpack-sources 0.2.3 MIT git+https://github.com/webpack/webpack-sources.git
wkx 0.5.0 MIT http://github.com/cschwarz/wkx.git
ws 7.4.6 MIT https://github.com/websockets/ws.git
xterm 4.12.0 MIT https://github.com/xtermjs/xterm.js
xterm-addon-fit 0.5.0 MIT https://github.com/xtermjs/xterm.js
xterm-addon-search 0.8.0 MIT https://github.com/xtermjs/xterm.js
xterm-addon-web-links 0.4.0 MIT https://github.com/xtermjs/xterm.js
yeast 0.1.2 MIT https://github.com/unshiftio/yeast.git
@fortawesome/fontawesome-free 5.15.3 (CC-BY-4.0 AND OFL-1.1 AND MIT) https://github.com/FortAwesome/Font-Awesome
@trysound/sax 0.1.1 ISC git://github.com/svg/sax.git
boolbase 1.0.0 ISC https://github.com/fb55/boolbase
css-declaration-sorter 6.0.0 ISC https://github.com/Siilwyn/css-declaration-sorter.git
electron-to-chromium 1.3.727 ISC https://github.com/kilian/electron-to-chromium/
css-declaration-sorter 6.0.3 ISC https://github.com/Siilwyn/css-declaration-sorter.git
electron-to-chromium 1.3.740 ISC https://github.com/kilian/electron-to-chromium/
icss-utils 5.1.0 ISC git+https://github.com/css-modules/icss-utils.git
is-resolvable 1.1.0 ISC https://github.com/shinnn/is-resolvable.git
lru-cache 6.0.0 ISC git://github.com/isaacs/node-lru-cache.git
@@ -357,7 +375,7 @@ bootstrap-datepicker 1.9.0
eve 0.5.4 Apache-2.0 git@github.com:adobe-webplatform/eve.git
paths-js 0.4.11 Apache-2.0 https://github.com/andreaferretti/paths-js.git
snapsvg 0.5.1 Apache-2.0 git@github.com:adobe-webplatform/Snap.svg.git
caniuse-lite 1.0.30001228 CC-BY-4.0 https://github.com/browserslist/caniuse-lite.git
caniuse-lite 1.0.30001230 CC-BY-4.0 https://github.com/browserslist/caniuse-lite.git
css-select 3.1.2 BSD-2-Clause git://github.com/fb55/css-select.git
css-what 4.0.0 BSD-2-Clause https://github.com/fb55/css-what
domelementtype 2.2.0 BSD-2-Clause git://github.com/fb55/domelementtype.git
@@ -379,12 +397,13 @@ istanbul-lib-source-maps 4.0.0
istanbul-reports 3.0.2 BSD-3-Clause git+ssh://git@github.com/istanbuljs/istanbuljs.git
source-map 0.5.7 BSD-3-Clause http://github.com/mozilla/source-map.git
source-map 0.6.1 BSD-3-Clause http://github.com/mozilla/source-map.git
source-map-js 0.6.2 BSD-3-Clause http://github.com/7rulnik/source-map.git
sprintf-js 1.1.2 BSD-3-Clause https://github.com/alexei/sprintf.js.git
mdn-data 2.0.14 CC0-1.0 https://github.com/mdn/data.git
mousetrap 1.6.5 Apache-2.0 WITH LLVM-exception git://github.com/ccampbell/mousetrap.git
precond 0.2.3 MIT* https://github.com/MathieuTurcotte/node-precond.git
webcabin-docker 2.2.4-dev MIT* Unknown
webcabin-docker 2.2.5 MIT* Unknown
tablesorter 2.31.3 (MIT OR GPL-2.0) git://github.com/Mottie/tablesorter.git
326 dependencies listed.
335 dependencies listed.
+1 -1
View File
@@ -142,7 +142,7 @@ msg-extract:
cd web && pybabel extract -F babel.cfg -o pgadmin/messages.pot pgadmin
msg-update:
cd web && pybabel update -i pgadmin/messages.pot -d pgadmin/translations
cd web && pybabel update --no-fuzzy-matching -i pgadmin/messages.pot -d pgadmin/translations
.PHONY: docs
+1 -1
View File
@@ -43,7 +43,7 @@ The configuration files are as follows:
Linux,/etc/pgadmin/config_system.py
macOS,/Library/Preferences/pgadmin/config_system.py
Windows,%CommonProgramFiles%\pgadmin\config_system.py
Windows,%CommonProgramFiles%\\pgadmin\\config_system.py
.. note:: If the SERVER_MODE setting is changed in ``config_distro.py``,
``config_local.py``, or ``config_system.py`` you will most likely need to
+20 -3
View File
@@ -23,8 +23,19 @@ server:
* PostgreSQL 12: */usr/local/pgsql-12*
* PostgreSQL 13: */usr/local/pgsql-13*
The most recent version of the utilities is used by default; this may be
changed in the :ref:`preferences`.
The default binary paths set in the container are as follows:
.. code-block:: bash
DEFAULT_BINARY_PATHS = {
'pg-13': '/usr/local/pgsql-13'
'pg-12': '/usr/local/pgsql-12'
'pg-11': '/usr/local/pgsql-11'
'pg-10': '/usr/local/pgsql-10'
'pg-9.6': '/usr/local/pgsql-9.6'
}
this may be changed in the :ref:`preferences`.
Environment Variables
*********************
@@ -104,7 +115,7 @@ Adjust the number of threads the Gunicorn server uses to handle incoming
requests. This should typically be left as-is, except in highly loaded systems
where it may be increased.
**PGADMIN_CONFIG_**
**PGADMIN_CONFIG_***
This is a variable prefix that can be used to override any of the configuration
options in pgAdmin's *config.py* file. Add the *PGADMIN_CONFIG_* prefix to any
@@ -117,6 +128,12 @@ is read after */pgadmin4/config.py* and before */pgadmin4/config_local.py*.
Any settings given will therefore override anything in config.py, but can be
overridden by settings in config_local.py.
Settings are only written to */pgadmin4/config_distro.py* once, typically on
first launch of the container. If */pgadmin4/config_distro.py* contains one or
more lines, then no changes are made; for example, if the container instance is
restarted, or */pgadmin4/config_distro.py* is mapped to a file on persistent
storage (not recommended - use */pgadmin4/config_local.py* instead)!
See :ref:`config_py` for more information on the available configuration settings.
Mapped Files and Directories
+1
View File
@@ -16,3 +16,4 @@ PL/SQL code.
editgrid
schema_diff
erd_tool
psql_tool
+1
View File
@@ -37,6 +37,7 @@ Mode is pre-configured for security.
change_user_password
ldap
kerberos
oauth2
.. note:: Pre-compiled and configured installation packages are available for
Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

+11
View File
@@ -34,6 +34,7 @@ from *config.py* file and modify the values for the following parameters.
Please note that if it is not set, it will take the value of
*default_server* parameter."
Keytab file for HTTP Service
============================
@@ -116,3 +117,13 @@ PostgreSQL Server settings to configure Kerberos Authentication
* Note that, you have to login into pgAdmin with Kerberos authentication to
then connect to PostgreSQL using Kerberos.
Master Password
===============
In the multi user mode, pgAdmin uses user's login password to encrypt/decrypt the PostgreSQL server password.
In the Kerberos authentication, the pgAdmin user does not have the password, so we need an encryption key to store
the PostgreSQL server password for the servers which are not configured to use the Kerberos authentication.
To accomplish this, set the configuration parameter MASTER_PASSWORD to *True*, so upon setting the master password,
it will be used as an encryption key while storing the password. If it is False, the server password can not be stored.
+2 -1
View File
@@ -18,4 +18,5 @@ database, right-click on the *Databases* node, and select *Create Database...*
move_objects
resource_group_dialog
role_dialog
tablespace_dialog
tablespace_dialog
role_reassign_dialog
+2
View File
@@ -128,6 +128,8 @@ Use the *Tools* menu to access the following options (in alphabetical order):
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| *Search Objects...* | Click to open the :ref:`Search Objects... <search_objects>` and start searching any kind of objects in a database. |
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| *PSQL Tool* | Click to open the :ref:`PSQL Tool <psql_tool>` and start PSQL in the current database context. |
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
The Help Menu
*************
+61
View File
@@ -0,0 +1,61 @@
.. _oauth2:
*****************************************
`Enabling OAUTH2 Authentication`:index:
*****************************************
To enable OAUTH2 authentication for pgAdmin, you must configure the OAUTH2
settings in the *config_local.py* or *config_system.py* file (see the
:ref:`config.py <config_py>` documentation) on the system where pgAdmin is
installed in Server mode. You can copy these settings from *config.py* file
and modify the values for the following parameters:
.. csv-table::
:header: "**Parameter**", "**Description**"
:class: longtable
:widths: 35, 55
"AUTHENTICATION_SOURCES", "The default value for this parameter is *internal*.
To enable OAUTH2 authentication, you must include *oauth2* in the list of values
for this parameter. you can modify the value as follows:
* [‘oauth2’, ‘internal’]: pgAdmin will display an additional button for authenticating with oauth2"
"OAUTH2_NAME", "The name of the Oauth2 provider, ex: Google, Github"
"OAUTH2_DISPLAY_NAME", "Oauth2 display name in pgAdmin"
"OAUTH2_CLIENT_ID", "Oauth2 Client ID"
"OAUTH2_CLIENT_SECRET", "Oauth2 Client Secret"
"OAUTH2_TOKEN_URL", "Oauth2 Access Token endpoint"
"OAUTH2_AUTHORIZATION_URL", "Endpoint for user authorization"
"OAUTH2_API_BASE_URL", "Oauth2 base URL endpoint to make requests simple, ex: *https://api.github.com/*"
"OAUTH2_USERINFO_ENDPOINT", "User Endpoint, ex: *user* (for github) and *useinfo* (for google)"
"OAUTH2_ICON", "The Font-awesome icon to be placed on the oauth2 button, ex: fa-github"
"OAUTH2_BUTTON_COLOR", "Oauth2 button color"
"OAUTH2_AUTO_CREATE_USER", "Set the value to *True* if you want to automatically
create a pgAdmin user corresponding to a successfully authenticated Oauth2 user.
Please note that password is not stored in the pgAdmin database."
Redirect URL
============
The redirect url to configure Oauth2 server is *http://<pgAdmin Server URL>/oauth2/authorize*
Master Password
===============
In the multi user mode, pgAdmin uses user's login password to encrypt/decrypt the PostgreSQL server password.
In the Oauth2 authentication, the pgAdmin does not store the user's password, so we need an encryption key to store
the PostgreSQL server password.
To accomplish this, set the configuration parameter MASTER_PASSWORD to *True*, so upon setting the master password,
it will be used as an encryption key while storing the password. If it is False, the server password can not be stored.
Login Page
============
After configuration, on restart, you can see the login page with the Oauth2 login button(s).
.. image:: images/oauth2_login.png
:alt: Oauth2 login
:align: center
+20 -11
View File
@@ -154,6 +154,9 @@ the graphs on the *Dashboard* tab:
:alt: Preferences dialog dashboard display options
:align: center
* Set the warning and alert threshold value to highlight the long-running
queries on the dashboard.
* When the *Show activity?* switch is set to *True*, activity tables will be
displayed on dashboards.
@@ -211,21 +214,23 @@ files.
:align: center
Use the fields on the *Binary paths* panel to specify the path to the directory
that contains the utility programs (pg_dump, pg_restore, and pg_dumpall) for
that contains the utility programs (pg_dump, pg_dumpall, pg_restore and psql) for
monitored databases:
* Use the *EDB Advanced Server Binary Path* field to specify the location of the
EDB Postgres Advanced Server utility programs. If this path is not set,
pgAdmin will attempt to find the utilities in standard locations used by
EnterpriseDB.
* Use the *EDB Advanced Server Binary Path* grid to specify the location of the
EDB Postgres Advanced Server utility programs based on the server version.
If the respective path is not set, then pgAdmin will pick up the path for which
'Set as default' is checked else pgAdmin will attempt to find the utilities in
standard locations used by EnterpriseDB.
* Use the *Greenplum Database Binary Path* field to specify the location of the
Greenplum database utility programs. If this path is not set, pgAdmin will
attempt to find the utilities in standard locations used by Greenplum.
* Use the *PostgreSQL Binary Path* grid to specify the location of the
PostgreSQL utility programs based on the server version. If the respective
path is not set, then pgAdmin will pick up the path for which 'Set as default'
is checked else pgAdmin will attempt to find the utilities in standard
locations used by PostgreSQL.
* Use the *PostgreSQL Binary Path* field to specify the location of the
PostgreSQL utility programs. If this path is not set, pgAdmin will attempt
to find the utilities in standard locations used by PostgreSQL.
**Note:** Use the 'Validate path' button to check the existence of the utility
programs (pg_dump, pg_dumpall, pg_restore and psql) and there respective versions.
.. image:: images/preferences_paths_help.png
:alt: Preferences dialog binary path help section
@@ -372,6 +377,10 @@ Use the fields on the *Options* panel to manage editor preferences.
Use the fields on the *Results grid* panel to specify your formatting
preferences for copied data.
* Specify the maximum width of the column when 'Resize by data?' is set to True.
If it is set to 0 then columns will auto-size to the maximum width of the data
in the column. If 'Resize by data?' is set to False then this setting won't
take any effect.
* When the *Resize by data?* switch is set to *True*, then data columns will
auto-size to the maximum width of the data in the column as loaded in the
first batch. If False, the column will be sized to the widest of the data
+30
View File
@@ -0,0 +1,30 @@
.. _psql_tool:
******************
`PSQL Tool`:index:
******************
The PSQL tool allows users to connect to PostgreSQL or EDB Advanced server using
the psql command line interface through their browser.
* Open the PSQL tool from the Tools or browser tree context menu, or use PSQL
tool button at the top of the browser tree.
* PSQL will connect to the current connected database from the browser tree.
.. image:: images/psql_tool.png
:alt: PSQL tool window
:align: center
You can open multiple instances of the PSQL tool in individual tabs simultaneously.
To close the PSQL tool, click the *X* in the upper-right hand corner of the tab bar.
**Note:** On the Windows platform, this feature is available on Windows 10 (1809
version), and Windows Server 2019 and onwards.
**Note:** The PSQL tool is always available when pgAdmin is running in Desktop
mode, but is disabled by default in Server mode. This is because users can run
arbitrary shell commands through psql which may be considered a security risk in
some deployments. System Administrators can enable the use of the PSQL tool in
the pgAdmin configuration by setting the *ENABLE_PSQL* option to *True*; see
:ref:`config_py` for more information.
+2
View File
@@ -11,6 +11,8 @@ notes for it.
.. toctree::
:maxdepth: 1
release_notes_5_5
release_notes_5_4
release_notes_5_3
release_notes_5_2
release_notes_5_1
+40
View File
@@ -0,0 +1,40 @@
************
Version 5.4
************
Release date: 2021-06-17
This release contains a number of bug fixes and new features since the release of pgAdmin4 5.3.
New features
************
| `Issue #1561 <https://redmine.postgresql.org/issues/1561>`_ - Added browse button to select the binary path in the Preferences.
| `Issue #1591 <https://redmine.postgresql.org/issues/1591>`_ - Added Grant Wizard option under Package node.
| `Issue #2341 <https://redmine.postgresql.org/issues/2341>`_ - Added support to launch PSQL for the connected database server.
| `Issue #4064 <https://redmine.postgresql.org/issues/4064>`_ - Added window maximize/restore functionality for properties dialog.
| `Issue #5370 <https://redmine.postgresql.org/issues/5370>`_ - Added support to set the binary path for the different database server versions.
| `Issue #6231 <https://redmine.postgresql.org/issues/6231>`_ - Added OS, Browser, Configuration details in the About dialog.
| `Issue #6395 <https://redmine.postgresql.org/issues/6395>`_ - Added support for rotating the pgAdmin log file on the basis of size and age.
| `Issue #6524 <https://redmine.postgresql.org/issues/6524>`_ - Support non-admin installation on Windows.
Housekeeping
************
| `Issue #4622 <https://redmine.postgresql.org/issues/4622>`_ - Added RESQL/MSQL test cases for Table and its child nodes.
| `Issue #6225 <https://redmine.postgresql.org/issues/6225>`_ - Updated Flask-Security-Too to the latest v4.
| `Issue #6460 <https://redmine.postgresql.org/issues/6460>`_ - Added a mechanism to detect a corrupt/broken config database file.
Bug fixes
*********
| `Issue #4203 <https://redmine.postgresql.org/issues/4203>`_ - Fixed the issue of renaming the database by another user.
| `Issue #6404 <https://redmine.postgresql.org/issues/6404>`_ - Ensure that the Query Tool connection string should not be changed as per the 'Query Tool tab title'.
| `Issue #6466 <https://redmine.postgresql.org/issues/6466>`_ - Ensure that the user should be able to add members in Login/Role group while creating it.
| `Issue #6469 <https://redmine.postgresql.org/issues/6469>`_ - Ensure that the calendar control should be disabled in the properties panel for Role.
| `Issue #6473 <https://redmine.postgresql.org/issues/6473>`_ - Disable browser password saving in the runtime.
| `Issue #6478 <https://redmine.postgresql.org/issues/6478>`_ - Fixed duplicate SQL issue for tables with more than one partition.
| `Issue #6482 <https://redmine.postgresql.org/issues/6482>`_ - Fixed an issue where the Foreground Color property of server dialog does not work.
| `Issue #6513 <https://redmine.postgresql.org/issues/6513>`_ - Fixed an issue where pgAdmin does not open after password reset in server mode.
| `Issue #6520 <https://redmine.postgresql.org/issues/6520>`_ - Fixed an issue where a decimal number is appended for character varying fields while downloading the data in CSV format.
+37
View File
@@ -0,0 +1,37 @@
************
Version 5.5
************
Release date: 2021-07-15
This release contains a number of bug fixes and new features since the release of pgAdmin4 5.4.
New features
************
| `Issue #1975 <https://redmine.postgresql.org/issues/1975>`_ - Highlighted long running queries on the dashboards.
| `Issue #3893 <https://redmine.postgresql.org/issues/3893>`_ - Added support for Reassign/Drop Owned for login roles.
| `Issue #3920 <https://redmine.postgresql.org/issues/3920>`_ - Do not block the query editor window when running a query.
| `Issue #5940 <https://redmine.postgresql.org/issues/5940>`_ - Added support for OAuth 2 authentication.
| `Issue #6559 <https://redmine.postgresql.org/issues/6559>`_ - Added option to provide maximum width of the column when 'Resize by data?’ option in the preferences is set to True.
Housekeeping
************
Bug fixes
*********
| `Issue #4189 <https://redmine.postgresql.org/issues/4189>`_ - Ensure that the Data Output panel can be snapped back after it is detached.
| `Issue #6388 <https://redmine.postgresql.org/issues/6388>`_ - Fixed replace keyboard shortcut issue in the query tool on the normal keyboard layout.
| `Issue #6398 <https://redmine.postgresql.org/issues/6398>`_ - Fixed an issue where detaching the query editor panel gives a blank white panel.
| `Issue #6427 <https://redmine.postgresql.org/issues/6427>`_ - Remove leading whitespace and replace it with '[...] ' in the Query Tool data grid so cells don't look empty.
| `Issue #6448 <https://redmine.postgresql.org/issues/6448>`_ - Fixed an issue in the search object when searching in 'all types' or 'subscription' if the user doesn't have access to the subscription.
| `Issue #6489 <https://redmine.postgresql.org/issues/6489>`_ - Fixed an issue where Execute/Refresh button should not be disabled when we run the empty query.
| `Issue #6505 <https://redmine.postgresql.org/issues/6505>`_ - Fixed an issue where the New Connection Drop Down has lost default maintenance database, auto-select, and tab-through functionality.
| `Issue #6536 <https://redmine.postgresql.org/issues/6536>`_ - Fixed directory selection issue with the folder dialog.
| `Issue #6541 <https://redmine.postgresql.org/issues/6541>`_ - Ensure that setting 'Open in new browser tab' should be visible, it should not be based on the value of 'ENABLE_PSQL'.
| `Issue #6547 <https://redmine.postgresql.org/issues/6547>`_ - Fixed copy/paste issues for PSQL tool terminal.
| `Issue #6550 <https://redmine.postgresql.org/issues/6550>`_ - Disable email deliverability check that was introduced in flask-security-too by default to maintain backwards compatibility.
| `Issue #6555 <https://redmine.postgresql.org/issues/6555>`_ - Fixed Czech translation string for 'Login' keyword.
| `Issue #6557 <https://redmine.postgresql.org/issues/6557>`_ - Fixed an issue where incorrect column name listed in the properties of Index.
+51
View File
@@ -0,0 +1,51 @@
.. _role_reassign_dialog:
**************************************
`Role Reassign/Drop Own Dialog`:index:
**************************************
Use the *Reassign/Drop Own* dialog to change the ownership of database objects owned
by a database role. This dialog instructs the system to change the ownership of database
objects owned by any of the *old_roles* to *new_role*.
The *Reassign/Drop Own* dialog organizes the Reassign & Drop role through General tab.
.. image:: images/role_reassign_dialog.png
:alt: Reassign/Drop Own dialog
:align: center
* Use the *Operation* field to provide Reassign option.
* Provide a new role in the *Reassign Objects to* field; The ownership of all the objects within the selected database,
and of all shared objects (databases, tablespaces), owned by the *old_role* will be reassigned to *new_role*.
* Provide a database on which the reassignment is to be carried out.
The above example demonstrates reassigning *old_role* to *new_role*.
Click the *SQL* tab to continue.
.. image:: images/role_reassign_dialog_sql.png
:alt: Reassign/Drop Own dialog sql
:align: center
Removing database objects owned by a database role.
.. image:: images/role_drop_dialog.png
:alt: Reassign/Drop Own dialog
:align: center
* Use the *Operation* field to provide Drop option.
* Use the *Cascade?* field to provide Yes, No is default.
* Provide a database on which the drop of objects is to be carried out.
Click the *SQL* tab to continue.
.. image:: images/role_drop_dialog_sql.png
:alt: Reassign/Drop Own dialog sql
:align: center
The above examples demonstrates drop owned by *role*.
* Click the *Help* button (?) to access online help.
* Click the *OK* button to save work.
* Click the *Cancel* button to exit without saving work.
+3 -1
View File
@@ -20,4 +20,6 @@ the selected browser node.
* Use the :ref:`Filtered Rows <viewdata_filter>` button to access the Data Filter popup
to apply a filter to a set of data for viewing/editing.
* Use the :ref:`Search objects <search_objects>` button to access the search objects
dialog. It helps you search any database object.
dialog. It helps you search any database object.
* Use the :ref:`PSQL Tool <psql_tool>` button to open the PSQL in the current
database context.
+6 -1
View File
@@ -10,7 +10,12 @@ CA_FILE = '/etc/ssl/certs/ca-certificates.crt'
LOG_FILE = '/dev/null'
HELP_PATH = '../../docs'
DEFAULT_BINARY_PATHS = {
'pg': '/usr/local/pgsql-13'
'pg': '/usr/local/pgsql-13',
'pg-13': '/usr/local/pgsql-13',
'pg-12': '/usr/local/pgsql-12',
'pg-11': '/usr/local/pgsql-11',
'pg-10': '/usr/local/pgsql-10',
'pg-9.6': '/usr/local/pgsql-9.6'
}
EOF
+29 -17
View File
@@ -6,21 +6,27 @@ builds may still work with suitable adjustments.
## Installing build requirements
1. Install Visual Studio 2017 Pro from https://my.visualstudio.com/Downloads?q=Visual%20Studio%202017
Choose the Desktop development with C++ option.
1. Install Visual Studio 2017 Pro from https://my.visualstudio.com/Downloads?q=Visual%20Studio%202017.
Choose the Desktop development with C++ option, and ensure that you add the
'Visual C++ MFC for x86 and x64' option.
2. Install Chocolatey from https://chocolatey.org/install#individual
3. Install various command line tools:
choco install -y bzip2 cmake diffutils dotnet3.5 gzip git innosetup nodejs-lts python strawberryperl wget yarn
choco install -y awk bzip2 cmake diffutils dotnet3.5 gnuwin32-coreutils.install gzip git html-help-workshop innosetup nodejs-lts python sed strawberryperl wget yarn
4. Upgrade pip (this may give a permissions error that can be ignored):
4. Ensure the GNU CoreUtils and Microsoft HTML Help Workshop are in the system path - add:
pip install --upgrade pip
* C:\Program Files (x86)\GnuWin32\bin
* C:\Program Files (x86)\HTML Help Workshop
5. Install virtualenv:
5. Upgrade pip:
python -m pip install --upgrade pip
6. Install virtualenv:
pip install virtualenv
@@ -39,19 +45,22 @@ prompt.
tar -zxvf zlib-1.2.11.tar.gz
cd zlib-1.2.11
cmake -DCMAKE_INSTALL_PREFIX=C:/build64/zlib -G "Visual Studio 15 2017 Win64" .
msbuild ALL_BUILD.vcxproj /p:Configuration=Release
msbuild RUN_TESTS.vcxproj /p:Configuration=Release
msbuild INSTALL.vcxproj /p:Configuration=Release
copy C:\build64\zlib\lib\zlib.lib C:\build64\zlib\lib\zdll.lib
cd ..
3. Download the OpenSSL source code, unpack and build it:
wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz
tar -zxvf openssl-1.1.1g.tar.gz
cd openssl-1.1.1g
wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
tar -zxvf openssl-1.1.1k.tar.gz
cd openssl-1.1.1k
perl Configure VC-WIN64A no-asm --prefix=C:\build64\openssl no-ssl2 no-ssl3 no-comp
nmake
nmake test
nmake install
cd ..
Note that if you are not working in an administrative account, you may need to
create and give your regular account appropriate permissions to write/modify
@@ -63,8 +72,10 @@ users could potentially write to.
In a *32bit* Visual Studio 2017 command prompt:
wget https://kerberos.org/dist/krb5/1.19/krb5-1.19.1.tar.gz
tar -zxvf krb5-1.19.1.tar.gz
mkdir C:\build64\krb5
cd krb5-1.18.3\src
cd krb5-1.19.1\src
set KRB_INSTALL_DIR=C:\build64\krb5
nmake -f Makefile.in prep-windows
@@ -75,17 +86,18 @@ users could potentially write to.
In a *64bit* Visual Studio 2017 command prompt:
cd krb5-1.18.3\src
cd krb5-1.19.1\src
set PATH=%PATH%;"%WindowsSdkVerBinPath%"\x86
set KRB_INSTALL_DIR=C:\build64\krb5
nmake NODEBUG=1
nmake install NODEBUG=1
cd ..\..
5. Download the PostgreSQL source code, unpack and build it:
wget https://ftp.postgresql.org/pub/source/v12.3/postgresql-13.1.tar.bz2
tar -zxvf postgresql-13.1.tar.gz
cd postgresql-13.1\src\tools\msvc
wget https://ftp.postgresql.org/pub/source/v13.3/postgresql-13.3.tar.gz
tar -zxvf postgresql-13.3.tar.gz
cd postgresql-13.3\src\tools\msvc
>> config.pl echo # Configuration arguments for vcbuild.
>> config.pl echo use strict;
@@ -154,9 +166,9 @@ Studio 2017 64bit command prompt. Note that the examples shown below are the
defaults for the build system, so if they match your requirements you don't
need to set them:
SET "PGADMIN_POSTGRES_DIR=C:\Program Files\PostgreSQL\13"
SET "PGADMIN_POSTGRES_DIR=C:\build64\pgsql"
SET "PGADMIN_PYTHON_DIR=C:\Python39"
SET "PGADMIN_KRB5_DIR=C:\jenkins\build64\krb5"
SET "PGADMIN_KRB5_DIR=C:\build64\krb5"
SET "PGADMIN_INNOTOOL_DIR=C:\Program Files (x86)\Inno Setup 6"
SET "PGADMIN_SIGNTOOL_DIR=C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x64"
SET "PGADMIN_VCREDIST_DIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Redist\MSVC\14.16.27012"
+8 -7
View File
@@ -19,7 +19,7 @@ AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={commonpf}\{#MyAppName}\{#MyAppVersion}
DefaultDirName={autopf}\{#MyAppName}\{#MyAppVersion}
DefaultGroupName={#MyAppName}
DisableWelcomePage=no
DisableProgramGroupPage=auto
@@ -28,9 +28,10 @@ OutputBaseFilename=pgadmin4-setup
SetupIconFile=Resources\pgAdmin4.ico
Compression=lzma
SolidCompression=yes
PrivilegesRequired=admin
PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
ChangesEnvironment=yes
;UninstallFilesDir={app}\{#MyAppVersion}
UninstallDisplayIcon={app}\runtime\{#MyAppExeName}
ArchitecturesInstallIn64BitMode={#MyAppArchitecturesMode}
AllowNoIcons=yes
WizardImageFile=sidebar.bmp
@@ -57,10 +58,10 @@ Source: "..\..\win-build\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdi
Filename: "{app}\installer\{#MyAppVCDist}"; StatusMsg: "VC runtime redistributable package"; Parameters: "/passive /verysilent /norestart"; Check: InstallVC;
[Registry]
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekeyifempty
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekey
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "Version"; ValueData: "{#MyAppFullVersion}"
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekeyifempty
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekey
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "Version"; ValueData: "{#MyAppFullVersion}"
[Code]
var
+8 -2
View File
@@ -8,7 +8,6 @@
#
###############################################################################
cheroot==8.*
Flask==1.*
Flask-Gravatar==0.*
Flask-Login==0.*
@@ -30,10 +29,17 @@ psycopg2==2.8.*
python-dateutil==2.*
SQLAlchemy==1.3.*
itsdangerous<=1.1.0
Flask-Security-Too==3.*
Flask-Security-Too==4.*
bcrypt==3.*
cryptography==3.*
sshtunnel==0.*
ldap3==2.*
Flask-BabelEx==0.*
gssapi==1.6.*
flask-socketio>=5.0.1
eventlet==0.31.0
httpagentparser==1.9.*
user-agents==2.2.0
pywinpty==1.1.1; sys_platform=="win32"
Authlib==0.15.*
requests==2.25.*
+1
View File
@@ -6,6 +6,7 @@
"author": "pgAdmin Development Team (https://www.pgadmin.org/)",
"license": "PostgreSQL",
"chromium-args": "--disable-popup-blocking",
"user-agent": "Nwjs:%nwver-%osinfo-%chromium_ver",
"window": {
"width": 440,
"height": 170,
+11
View File
@@ -28,6 +28,17 @@
margin-bottom: 10px;
}
</style>
<!-- Disable/block all password saving in nw.js -->
<script type="text/javascript">
chrome.passwordsPrivate.getSavedPasswordList(function(passwords) {
passwords.forEach((p, i) => {
chrome.passwordsPrivate.removeSavedPassword(i);
});
});
chrome.privacy.services.passwordSavingEnabled.set({ value: false });
</script>
<script type="text/javascript">
let platform = require("os").platform;
</script>
+98 -9
View File
@@ -43,7 +43,7 @@ APP_ICON = 'pg-icon'
# Application version number components
APP_RELEASE = 5
APP_REVISION = 3
APP_REVISION = 5
# Application version suffix, e.g. 'beta1', 'dev'. Usually an empty string
# for GA releases.
@@ -52,7 +52,7 @@ APP_SUFFIX = ''
# Numeric application version for upgrade checks. Should be in the format:
# [X]XYYZZ, where X is the release version, Y is the revision, with a leading
# zero if needed, and Z represents the suffix, with a leading zero if needed
APP_VERSION_INT = 50300
APP_VERSION_INT = 50500
# DO NOT CHANGE!
# The application version string, constructed from the components
@@ -156,8 +156,8 @@ X_FRAME_OPTIONS = "SAMEORIGIN"
# such as JavaScript, CSS, or pretty much anything that the browser loads.
# see https://content-security-policy.com/#source_list for more info
# e.g. "default-src https: data: 'unsafe-inline' 'unsafe-eval';"
CONTENT_SECURITY_POLICY = "default-src http: data: blob: 'unsafe-inline' " \
"'unsafe-eval';"
CONTENT_SECURITY_POLICY = "default-src ws: http: data: blob: 'unsafe-inline'" \
" 'unsafe-eval';"
# STRICT_TRANSPORT_SECURITY_ENABLED when set to True will set the
# Strict-Transport-Security header
@@ -286,6 +286,13 @@ if SERVER_MODE and not IS_WIN:
else:
LOG_FILE = os.path.join(DATA_DIR, 'pgadmin4.log')
# Log rotation setting
# Log file will be rotated considering values for LOG_ROTATION_SIZE
# & LOG_ROTATION_AGE. Rotated file will be named in format
# - LOG_FILE.Y-m-d_H-M-S
LOG_ROTATION_SIZE = 10 # In MBs
LOG_ROTATION_AGE = 1440 # In minutes
LOG_ROTATION_MAX_LOG_FILES = 90 # Maximum number of backups to retain
##########################################################################
# Server Connection Driver Settings
##########################################################################
@@ -374,6 +381,17 @@ SECURITY_EMAIL_SUBJECT_PASSWORD_NOTICE = "Your %s password has been reset" \
SECURITY_EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE = \
"Your password for %s has been changed" % APP_NAME
##########################################################################
# Email address validation
##########################################################################
# flask-security-too will validate email addresses and check deliverability
# by default. Disable the deliverability check by default, which was the old
# behaviour in <= v5.3
CHECK_EMAIL_DELIVERABILITY = False
SECURITY_EMAIL_VALIDATOR_ARGS = \
{"check_deliverability": CHECK_EMAIL_DELIVERABILITY}
##########################################################################
# Upgrade checks
##########################################################################
@@ -416,6 +434,10 @@ STORAGE_DIR = os.path.join(DATA_DIR, 'storage')
#
# A default location can be specified for each database driver ID, in
# a dictionary. Either an absolute or relative path can be specified.
#
# Version-specific defaults can also be specified, which will take priority
# over un-versioned paths.
#
# In cases where it may be difficult to know what the working directory
# is, "$DIR" can be specified. This will be replaced with the path to the
# top-level pgAdmin4.py file. For example, on macOS we might use:
@@ -425,8 +447,17 @@ STORAGE_DIR = os.path.join(DATA_DIR, 'storage')
##########################################################################
DEFAULT_BINARY_PATHS = {
"pg": "",
"pg-9.6": "",
"pg-10": "",
"pg-11": "",
"pg-12": "",
"pg-13": "",
"ppas": "",
"gpdb": ""
"ppas-9.6": "",
"ppas-10": "",
"ppas-11": "",
"ppas-12": "",
"ppas-13": ""
}
##########################################################################
@@ -531,10 +562,11 @@ ENHANCED_COOKIE_PROTECTION = True
##########################################################################
# Default setting is internal
# External Supported Sources: ldap, kerberos
# External Supported Sources: ldap, kerberos, oauth2
# Multiple authentication can be achieved by setting this parameter to
# ['ldap', 'internal']. pgAdmin will authenticate the user with ldap first,
# in case of failure internal authentication will be done.
# ['ldap', 'internal'] or ['oauth2', 'internal'] etc.
# pgAdmin will authenticate the user with ldap/oauth2 whatever first in the
# list, in case of failure the second authentication option will be considered.
AUTHENTICATION_SOURCES = ['internal']
@@ -614,7 +646,6 @@ LDAP_CA_CERT_FILE = ''
LDAP_CERT_FILE = ''
LDAP_KEY_FILE = ''
##########################################################################
# Kerberos Configuration
##########################################################################
@@ -636,6 +667,62 @@ KRB_AUTO_CREATE_USER = True
KERBEROS_CCACHE_DIR = os.path.join(DATA_DIR, 'krbccache')
##########################################################################
# OAuth2 Configuration
##########################################################################
# Multiple OAUTH2 providers can be added in the list like [{...},{...}]
# All parameters are required
OAUTH2_CONFIG = [
{
# The name of the of the oauth provider, ex: github, google
'OAUTH2_NAME': None,
# The display name, ex: Google
'OAUTH2_DISPLAY_NAME': '<Oauth2 Display Name>',
# Oauth client id
'OAUTH2_CLIENT_ID': None,
# Oauth secret
'OAUTH2_CLIENT_SECRET': None,
# URL to generate a token,
# Ex: https://github.com/login/oauth/access_token
'OAUTH2_TOKEN_URL': None,
# URL is used for authentication,
# Ex: https://github.com/login/oauth/authorize
'OAUTH2_AUTHORIZATION_URL': None,
# Oauth base url, ex: https://api.github.com/
'OAUTH2_API_BASE_URL': None,
# Name of the Endpoint, ex: user
'OAUTH2_USERINFO_ENDPOINT': None,
# Font-awesome icon, ex: fa-github
'OAUTH2_ICON': None,
# UI button colour, ex: #0000ff
'OAUTH2_BUTTON_COLOR': None,
}
]
# After Oauth authentication, user will be added into the SQLite database
# automatically, if set to True.
# Set it to False, if user should not be added automatically,
# in this case Admin has to add the user manually in the SQLite database.
OAUTH2_AUTO_CREATE_USER = True
##########################################################################
# PSQL tool settings
##########################################################################
# This will enable PSQL tool in pgAdmin when running in server mode.
# PSQL is always enabled in Desktop mode, however in server mode it is
# disabled by default because users can run arbitrary commands on the
# server through it.
ENABLE_PSQL = False
##########################################################################
# ENABLE_BINARY_PATH_BROWSING setting is used to enable the browse button
# while selecting binary path for the database server in server mode.
# In Desktop mode it is always enabled and setting is of no use.
##########################################################################
ENABLE_BINARY_PATH_BROWSING = False
##########################################################################
# Local config settings
@@ -676,3 +763,5 @@ if 'PGADMIN_CONFIG_DEFAULT_SERVER' in os.environ:
# Disable USER_INACTIVITY_TIMEOUT when SERVER_MODE=False
if not SERVER_MODE:
USER_INACTIVITY_TIMEOUT = 0
# Enable PSQL in Desktop Mode.
ENABLE_PSQL = True
+57
View File
@@ -0,0 +1,57 @@
"""empty message
Revision ID: c465fee44968
Revises: d0bc9f32b2b9
Create Date: 2021-06-04 14:42:12.843116
"""
from pgadmin.model import db, User
import uuid
# revision identifiers, used by Alembic.
revision = 'c465fee44968'
down_revision = 'd0bc9f32b2b9'
branch_labels = None
depends_on = None
def upgrade():
db.engine.execute("ALTER TABLE user RENAME TO user_old")
db.engine.execute("""
CREATE TABLE user (
id INTEGER NOT NULL,
username VARCHAR(256) NOT NULL,
email VARCHAR(256),
password VARCHAR(256),
active BOOLEAN NOT NULL,
confirmed_at DATETIME,
masterpass_check VARCHAR(256),
auth_source VARCHAR(256) NOT NULL DEFAULT 'internal',
fs_uniquifier NOT NULL UNIQUE,
PRIMARY KEY (id),
UNIQUE (username, auth_source),
CHECK (active IN (0, 1))
);
""")
user_old = db.engine.execute(
'select id, username, email, password, active, '
'confirmed_at, masterpass_check, auth_source '
'from user_old')
db.engine.execute(User.__table__.insert(), [
{
**row,
'fs_uniquifier': uuid.uuid4().hex
} for row in user_old
])
db.engine.execute("DROP TABLE user_old")
def downgrade():
# pgAdmin only upgrades, downgrade not implemented.
pass
+7 -2
View File
@@ -117,13 +117,18 @@
"shim-loader": "^1.0.1",
"slickgrid": "git+https://github.com/6pac/SlickGrid.git#2.3.16",
"snapsvg-cjs": "^0.0.6",
"socket.io-client": "^4.0.0",
"split.js": "^1.5.10",
"tablesorter": "^2.31.2",
"tempusdominus-bootstrap-4": "^5.1.2",
"tempusdominus-core": "^5.0.3",
"underscore": "^1.13.1",
"webcabin-docker": "git+https://github.com/EnterpriseDB/wcDocker/#c4a3398b89588408dc705895675bce7bd7660d36",
"wkx": "^0.5.0"
"webcabin-docker": "git+https://github.com/EnterpriseDB/wcDocker/#06daee1a8111b4ed08d58670674a2967e4f68313",
"wkx": "^0.5.0",
"xterm": "^4.11.0",
"xterm-addon-fit": "^0.5.0",
"xterm-addon-search": "^0.8.0",
"xterm-addon-web-links": "^0.4.0"
},
"scripts": {
"linter": "yarn eslint --no-eslintrc -c .eslintrc.js --ext .js --ext .jsx .",
+12 -11
View File
@@ -13,7 +13,7 @@ to start a web server."""
import sys
from cheroot.wsgi import Server as CherootServer
if sys.version_info < (3, 4):
raise RuntimeError('This application must be run under Python 3.4 '
@@ -37,7 +37,7 @@ else:
builtins.SERVER_MODE = None
import config
from pgadmin import create_app
from pgadmin import create_app, socketio
from pgadmin.utils import u_encode, fs_encoding, file_quote
from pgadmin.utils.constants import INTERNAL
# Get the config database schema version. We store this in pgadmin.model
@@ -97,6 +97,8 @@ if not os.path.isfile(config.SQLITE_PATH):
##########################################################################
app = create_app()
app.debug = False
app.config['sessions'] = dict()
if config.SERVER_MODE:
app.wsgi_app = ReverseProxied(app.wsgi_app)
@@ -206,17 +208,16 @@ def main():
else:
# Can use cheroot instead of flask dev server when not in debug
# 10 is default thread count in CherootServer
num_threads = 10 if config.THREADED_MODE else 1
prod_server = CherootServer(
(config.DEFAULT_SERVER, config.EFFECTIVE_SERVER_PORT),
wsgi_app=app,
numthreads=num_threads,
server_name=config.APP_NAME)
# num_threads = 10 if config.THREADED_MODE else 1
try:
print("Using production server...")
prod_server.start()
socketio.run(
app,
host=config.DEFAULT_SERVER,
port=config.EFFECTIVE_SERVER_PORT,
)
except KeyboardInterrupt:
prod_server.stop()
print("CLOSE SERVER")
socketio.stop()
except IOError:
app.logger.error("Error starting the app server: %s", sys.exc_info())
+88 -17
View File
@@ -14,11 +14,14 @@ import os
import sys
import re
import ipaddress
import traceback
from types import MethodType
from collections import defaultdict
from importlib import import_module
from flask import Flask, abort, request, current_app, session, url_for
from flask_socketio import SocketIO
from werkzeug.exceptions import HTTPException
from flask_babelex import Babel, gettext
from flask_babelex import gettext as _
@@ -37,25 +40,31 @@ from pgadmin.utils import PgAdminModule, driver, KeyManager
from pgadmin.utils.preferences import Preferences
from pgadmin.utils.session import create_session_interface, pga_unauthorised
from pgadmin.utils.versioned_template_loader import VersionedTemplateLoader
from datetime import timedelta
from pgadmin.setup import get_version, set_version
from datetime import timedelta, datetime
from pgadmin.setup import get_version, set_version, check_db_tables
from pgadmin.utils.ajax import internal_server_error, make_json_response
from pgadmin.utils.csrf import pgCSRFProtect
from pgadmin import authenticate
from pgadmin.utils.security_headers import SecurityHeaders
from pgadmin.utils.constants import KERBEROS
from pgadmin.utils.constants import KERBEROS, OAUTH2, INTERNAL, LDAP
# Explicitly set the mime-types so that a corrupted windows registry will not
# affect pgAdmin 4 to be load properly. This will avoid the issues that may
# occur due to security fix of X_CONTENT_TYPE_OPTIONS = "nosniff".
import mimetypes
mimetypes.add_type('application/javascript', '.js')
mimetypes.add_type('text/css', '.css')
winreg = None
if os.name == 'nt':
import winreg
socketio = SocketIO(manage_session=False, async_mode='threading',
logger=False, engineio_logger=False, debug=False,
ping_interval=25, ping_timeout=120)
class PgAdmin(Flask):
def __init__(self, *args, **kwargs):
@@ -256,7 +265,13 @@ def create_app(app_name=None):
create_app_data_directory(config)
# File logging
fh = logging.FileHandler(config.LOG_FILE, encoding='utf-8')
from pgadmin.utils.enhanced_log_rotation import \
EnhancedRotatingFileHandler
fh = EnhancedRotatingFileHandler(config.LOG_FILE,
config.LOG_ROTATION_SIZE,
config.LOG_ROTATION_AGE,
config.LOG_ROTATION_MAX_LOG_FILES)
fh.setLevel(config.FILE_LOG_LEVEL)
fh.setFormatter(logging.Formatter(config.FILE_LOG_FORMAT))
app.logger.addHandler(fh)
@@ -293,7 +308,7 @@ def create_app(app_name=None):
if current_user.is_authenticated:
user_id = current_user.id
else:
user = user_datastore.get_user(config.DESKTOP_USER)
user = user_datastore.find_user(email=config.DESKTOP_USER)
if user is not None:
user_id = user.id
user_language = Preferences.raw_value(
@@ -337,6 +352,44 @@ def create_app(app_name=None):
##########################################################################
# Upgrade the schema (if required)
##########################################################################
def backup_db_file():
"""
Create a backup of the current database file
and create new database file with default settings.
"""
backup_file_name = "{0}.{1}".format(
SQLITE_PATH, datetime.now().strftime('%Y%m%d%H%M%S'))
os.rename(SQLITE_PATH, backup_file_name)
app.logger.error('Exception in database migration.')
app.logger.info('Creating new database file.')
try:
db_upgrade(app)
os.environ[
'CORRUPTED_DB_BACKUP_FILE'] = backup_file_name
app.logger.info('Database migration completed.')
except Exception as e:
app.logger.error('Database migration failed')
app.logger.error(traceback.format_exc())
raise RuntimeError('Migration failed')
def upgrade_db():
"""
Execute the migrations.
"""
try:
db_upgrade(app)
os.environ['CORRUPTED_DB_BACKUP_FILE'] = ''
except Exception as e:
backup_db_file()
# check all tables are present in the db.
is_db_error, invalid_tb_names = check_db_tables()
if is_db_error:
app.logger.error(
'Table(s) {0} are missing in the'
' database'.format(invalid_tb_names))
backup_db_file()
with app.app_context():
# Run migration for the first time i.e. create database
from config import SQLITE_PATH
@@ -344,25 +397,34 @@ def create_app(app_name=None):
# If version not available, user must have aborted. Tables are not
# created and so its an empty db
if not os.path.exists(SQLITE_PATH) or get_version() == -1:
version = get_version()
if not os.path.exists(SQLITE_PATH) or version == -1:
# If running in cli mode then don't try to upgrade, just raise
# the exception
if not cli_mode:
db_upgrade(app)
upgrade_db()
else:
if not os.path.exists(SQLITE_PATH):
raise FileNotFoundError(
'SQLite database file "' + SQLITE_PATH +
'" does not exists.')
raise RuntimeError('Specified SQLite database file '
'is not valid.')
raise RuntimeError(
'The configuration database file is not valid.')
else:
schema_version = get_version()
# Run migration if current schema version is greater than the
# schema version stored in version table
if CURRENT_SCHEMA_VERSION >= schema_version:
db_upgrade(app)
upgrade_db()
else:
# check all tables are present in the db.
is_db_error, invalid_tb_names = check_db_tables()
if is_db_error:
app.logger.error(
'Table(s) {0} are missing in the'
' database'.format(invalid_tb_names))
backup_db_file()
# Update schema version to the latest
if CURRENT_SCHEMA_VERSION > schema_version:
@@ -404,6 +466,15 @@ def create_app(app_name=None):
# CSRF Token expiration till session expires
'WTF_CSRF_TIME_LIMIT': getattr(config, 'CSRF_TIME_LIMIT', None),
'WTF_CSRF_METHODS': ['GET', 'POST', 'PUT', 'DELETE'],
# Disable deliverable check for email addresss
'SECURITY_EMAIL_VALIDATOR_ARGS': config.SECURITY_EMAIL_VALIDATOR_ARGS
}))
app.config.update(dict({
'INTERNAL': INTERNAL,
'LDAP': LDAP,
'KERBEROS': KERBEROS,
'OAUTH2': OAUTH2
}))
security.init_app(app, user_datastore)
@@ -685,7 +756,7 @@ def create_app(app_name=None):
abort(401)
if not config.SERVER_MODE and not current_user.is_authenticated:
user = user_datastore.get_user(config.DESKTOP_USER)
user = user_datastore.find_user(email=config.DESKTOP_USER)
# Throw an error if we failed to find the desktop user, to give
# the sysadmin a hint. We'll continue to try to login anyway as
# that'll through a nice 500 error for us.
@@ -697,19 +768,18 @@ def create_app(app_name=None):
)
abort(401)
login_user(user)
elif config.SERVER_MODE and\
app.PGADMIN_EXTERNAL_AUTH_SOURCE ==\
KERBEROS and \
elif config.SERVER_MODE and \
not current_user.is_authenticated and \
request.endpoint in ('redirects.index', 'security.login'):
return authenticate.login()
if app.PGADMIN_EXTERNAL_AUTH_SOURCE == KERBEROS:
return authenticate.login()
# if the server is restarted the in memory key will be lost
# but the user session may still be active. Logout the user
# to get the key again when login
if config.SERVER_MODE and current_user.is_authenticated and \
app.PGADMIN_EXTERNAL_AUTH_SOURCE != \
KERBEROS and \
KERBEROS and app.PGADMIN_EXTERNAL_AUTH_SOURCE != \
OAUTH2 and\
current_app.keyManager.get() is None and \
request.endpoint not in ('security.login', 'security.logout'):
logout_user()
@@ -811,4 +881,5 @@ def create_app(app_name=None):
##########################################################################
# All done!
##########################################################################
socketio.init_app(app)
return app
+67 -5
View File
@@ -10,13 +10,17 @@
"""A blueprint module implementing the about box."""
import sys
from flask import Response, render_template, __version__, url_for
from flask import Response, render_template, __version__, url_for, request
from flask_babelex import gettext
from flask_security import current_user, login_required
from pgadmin.utils import PgAdminModule
from pgadmin.utils.menu import MenuItem
from pgadmin.utils.constants import MIMETYPE_APP_JS
import config
import httpagentparser
from pgadmin.model import User
from user_agents import parse
import platform
MODULE_NAME = 'about'
@@ -59,23 +63,81 @@ blueprint = AboutModule(MODULE_NAME, __name__, static_url_path='')
@login_required
def index():
"""Render the about box."""
info = {
'python_version': sys.version,
'flask_version': __version__
}
info = {}
# Get OS , NW.js, Browser details
browser, os_details, nwjs_version = detect_browser(request)
if nwjs_version:
info['nwjs'] = nwjs_version
info['browser_details'] = browser
info['os_details'] = os_details
info['config_db'] = config.SQLITE_PATH
info['log_file'] = config.LOG_FILE
if config.SERVER_MODE:
info['app_mode'] = gettext('Server')
admin = is_admin(current_user.email)
info['admin'] = admin
else:
info['app_mode'] = gettext('Desktop')
info['current_user'] = current_user.email
settings = ""
for setting in dir(config):
if not setting.startswith('_') and setting.isupper() and \
setting not in ['CSRF_SESSION_KEY',
'SECRET_KEY',
'SECURITY_PASSWORD_SALT',
'SECURITY_PASSWORD_HASH',
'ALLOWED_HOSTS',
'MAIL_PASSWORD',
'LDAP_BIND_PASSWORD',
'SECURITY_PASSWORD_HASH']:
if isinstance(getattr(config, setting), str):
settings = \
settings + '{} = "{}"\n'.format(
setting, gettext(getattr(config, setting)))
else:
settings = \
settings + '{} = {}\n'.format(
setting, gettext(getattr(config, setting)))
info['settings'] = settings
return render_template(
MODULE_NAME + '/index.html', info=info, _=gettext
)
def is_admin(load_user):
user = User.query.filter_by(email=load_user).first()
return user.has_role("Administrator")
def detect_browser(request):
"""This function returns the browser and os details"""
nwjs_version = None
agent = request.environ.get('HTTP_USER_AGENT')
os_details = parse(platform.platform()).ua_string
if 'Nwjs' in agent:
agent = agent.split('-')
nwjs_version = agent[0].split(':')[1]
browser = 'Chromium' + ' ' + agent[2]
else:
browser = httpagentparser.detect(agent)
if not browser:
browser = agent.split('/')[0]
else:
browser = browser['browser']['name'] + ' ' + browser['browser'][
'version']
return browser, os_details, nwjs_version
@blueprint.route("/about.js")
@login_required
def script():
+27 -7
View File
@@ -9,9 +9,9 @@
define(
['jquery', 'alertify', 'sources/pgadmin', 'sources/gettext',
'sources/url_for','sources/utils',
'sources/url_for','sources/utils','pgadmin.user_management.current_user',
],
function($, alertify, pgAdmin, gettext, url_for, commonUtils) {
function($, alertify, pgAdmin, gettext, url_for, commonUtils, current_user) {
pgAdmin = pgAdmin || window.pgAdmin || {};
/* Return back, this has been called more than once */
@@ -45,14 +45,28 @@ define(
},
hooks:{
onshow:function(){
var self = this;
var container = $(this.elements.footer).find('button:not([disabled])');
commonUtils.findAndSetFocus(container);
$('#copy_textarea').on('click', function(){
//Copy the server configuration details
let textarea = document.getElementById('about-textarea');
textarea.select();
document.execCommand('copy');
$('#copy_textarea').text('Copied');
});
$(this.elements.resizeHandle).on('click', function(){
// Set the height of the Textarea
var height = self.elements.dialog.scrollHeight - 300;
if (height < 0)
height = self.elements.dialog.scrollHeight - 150;
$('#about-textarea').css({'height':height});
});
},
},
prepare:function() {
this.setContent(this.message);
},
};
});
@@ -60,9 +74,15 @@ define(
$.get(url_for('about.index'),
function(data) {
alertify.aboutDialog(
gettext('About %s', pgAdmin.Browser.utils.app_name), data
).resizeTo(pgAdmin.Browser.stdW.md, pgAdmin.Browser.stdH.md);
if(!current_user.is_admin && pgAdmin.server_mode){
alertify.aboutDialog(
gettext('About %s', pgAdmin.Browser.utils.app_name), data
).resizeTo(pgAdmin.Browser.stdW.md, 300);
}else{
alertify.aboutDialog(
gettext('About %s', pgAdmin.Browser.utils.app_name), data
).resizeTo(750, 470);
}
});
},
};
+32 -17
View File
@@ -3,18 +3,6 @@
<div class="col-sm-3"><strong>{{ _('Version') }}</strong></div>
<div class="col-sm-9">{{ config.APP_VERSION }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Copyright') }}</strong></div>
<div class="col-sm-9">{{ config.APP_COPYRIGHT }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Python Version') }}</strong></div>
<div class="col-sm-9">{{ info.python_version }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Flask Version') }}</strong></div>
<div class="col-sm-9">{{ info.flask_version }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Application Mode') }}</strong></div>
<div class="col-sm-9">{{ info.app_mode }}</div>
@@ -23,10 +11,37 @@
<div class="col-sm-3"><strong>{{ _('Current User') }}</strong></div>
<div class="col-sm-9">{{ info.current_user }}</div>
</div>
<div class="row">
<div class="col-12 text-right"><img
src="{{ url_for('static', filename='img/logo-right-128.png') }}"
alt="{{ config.APP_NAME }} {{ _('logo') }}"
></div>
{% if info.nwjs %}
<div class="row">
<div class="col-sm-3"><strong>{{ _('NW.js Version') }}</strong></div>
<div class="col-sm-9">{{ info.nwjs }}</div>
</div>
{% endif %}
<div class="row">
<div class="col-sm-3"><strong>{{ _('Browser') }}</strong></div>
<div class="col-sm-9">{{ info.browser_details }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Operating System') }}</strong></div>
<div class="col-sm-9">{{ info.os_details }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('pgAdmin Database File') }}</strong></div>
<div class="col-sm-9">{{ info.config_db }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Log File') }}</strong></div>
<div class="col-sm-9">{{ info.log_file }}</div>
</div>
{%if (info.app_mode == 'Desktop') or (info.app_mode == 'Server' and info.admin)%}
<div class="row">
<div class="col-sm-3"><b>{{ _('Server Configuration') }}</b></div>
</div>
<div class="row">
<div class="col-sm-9">
<textarea id="about-textarea" rows="7" cols="150" style="position: relative;width:105%; white-space: pre-wrap;" readonly>{{ info.settings|safe }}</textarea>
<button class="btn btn-secondary about-copy" id="copy_textarea" style="position:absolute;top:0;right:0;z-index:20;">Copy</button>
</div>
</div>
{% endif %}
</div>
+61 -137
View File
@@ -9,68 +9,33 @@
"""A blueprint module implementing the Authentication."""
import flask
import pickle
from flask import current_app, flash, Response, request, url_for,\
render_template
from flask_babelex import gettext
from flask_security import current_user, login_required
from flask_security.views import _security, _ctx
from flask_security.utils import config_value, get_post_logout_redirect, \
get_post_login_redirect, logout_user
from pgadmin.utils.ajax import make_json_response, internal_server_error
import os
from flask import session
import config
from pgadmin.utils import PgAdminModule
from pgadmin.utils.constants import KERBEROS
from pgadmin.utils.csrf import pgCSRFProtect
import copy
from flask import current_app, flash, Response, request, url_for,\
session, redirect
from flask_babelex import gettext
from flask_security.views import _security
from flask_security.utils import get_post_logout_redirect, \
get_post_login_redirect
from pgadmin.utils import PgAdminModule
from pgadmin.utils.constants import KERBEROS, INTERNAL, OAUTH2, LDAP
from pgadmin.authenticate.registry import AuthSourceRegistry
from .registry import AuthSourceRegistry
MODULE_NAME = 'authenticate'
auth_obj = None
class AuthenticateModule(PgAdminModule):
def get_exposed_url_endpoints(self):
return ['authenticate.login',
'authenticate.kerberos_login',
'authenticate.kerberos_logout',
'authenticate.kerberos_update_ticket',
'authenticate.kerberos_validate_ticket']
return ['authenticate.login']
blueprint = AuthenticateModule(MODULE_NAME, __name__, static_url_path='')
@blueprint.route("/login/kerberos",
endpoint="kerberos_login", methods=["GET"])
@pgCSRFProtect.exempt
def kerberos_login():
logout_user()
return Response(render_template("browser/kerberos_login.html",
login_url=url_for('security.login'),
))
@blueprint.route("/logout/kerberos",
endpoint="kerberos_logout", methods=["GET"])
@pgCSRFProtect.exempt
def kerberos_logout():
logout_user()
if 'KRB5CCNAME' in session:
# Remove the credential cache
cache_file_path = session['KRB5CCNAME'].split(":")[1]
if os.path.exists(cache_file_path):
os.remove(cache_file_path)
return Response(render_template("browser/kerberos_logout.html",
login_url=url_for('security.login'),
))
@blueprint.route('/login', endpoint='login', methods=['GET', 'POST'])
def login():
"""
@@ -78,15 +43,20 @@ def login():
The user input will be validated and authenticated.
"""
form = _security.login_form()
auth_obj = AuthSourceManager(form, config.AUTHENTICATION_SOURCES)
session['_auth_source_manager_obj'] = None
auth_obj = AuthSourceManager(form, copy.deepcopy(
config.AUTHENTICATION_SOURCES))
if OAUTH2 in config.AUTHENTICATION_SOURCES\
and 'oauth2_button' in request.form:
session['auth_obj'] = auth_obj
session['auth_source_manager'] = None
# Validate the user
if not auth_obj.validate():
for field in form.errors:
for error in form.errors[field]:
flash(error, 'warning')
return flask.redirect(get_post_logout_redirect())
return redirect(get_post_logout_redirect())
# Authenticate the user
status, msg = auth_obj.authenticate()
@@ -94,34 +64,42 @@ def login():
# Login the user
status, msg = auth_obj.login()
current_auth_obj = auth_obj.as_dict()
if not status:
if current_auth_obj['current_source'] ==\
KERBEROS:
return flask.redirect('{0}?next={1}'.format(url_for(
return redirect('{0}?next={1}'.format(url_for(
'authenticate.kerberos_login'), url_for('browser.index')))
flash(msg, 'danger')
return flask.redirect(get_post_logout_redirect())
session['_auth_source_manager_obj'] = current_auth_obj
return flask.redirect(get_post_login_redirect())
return redirect(get_post_logout_redirect())
session['auth_source_manager'] = current_auth_obj
if 'auth_obj' in session:
session.pop('auth_obj')
return redirect(get_post_login_redirect())
elif isinstance(msg, Response):
return msg
elif 'oauth2_button' in request.form and not isinstance(msg, str):
return msg
if 'auth_obj' in session:
session.pop('auth_obj')
flash(msg, 'danger')
response = flask.redirect(get_post_logout_redirect())
response = redirect(get_post_logout_redirect())
return response
class AuthSourceManager():
class AuthSourceManager:
"""This class will manage all the authentication sources.
"""
def __init__(self, form, sources):
self.form = form
self.auth_sources = sources
self.source = None
self.source_friendly_name = None
self.current_source = None
self.source_friendly_name = INTERNAL
self.current_source = INTERNAL
self.update_auth_sources()
def as_dict(self):
"""
@@ -135,6 +113,17 @@ class AuthSourceManager():
return res
def update_auth_sources(self):
for auth_src in [KERBEROS, OAUTH2]:
if auth_src in self.auth_sources:
if 'internal_button' in request.form:
self.auth_sources.remove(auth_src)
else:
if INTERNAL in self.auth_sources:
self.auth_sources.remove(INTERNAL)
if LDAP in self.auth_sources:
self.auth_sources.remove(LDAP)
def set_current_source(self, source):
self.current_source = source
@@ -170,36 +159,19 @@ class AuthSourceManager():
msg = None
for src in self.auth_sources:
source = get_auth_sources(src)
self.set_source(source)
current_app.logger.debug(
"Authentication initiated via source: %s" %
source.get_source_name())
if self.form.data['email'] and self.form.data['password'] and \
source.get_source_name() == KERBEROS:
msg = gettext('pgAdmin internal user authentication'
' is not enabled, please contact administrator.')
continue
status, msg = source.authenticate(self.form)
# When server sends Unauthorized header to get the ticket over HTTP
# OR When kerberos authentication failed while accessing pgadmin,
# we need to break the loop as no need to authenticate further
# even if the authentication sources set to multiple
if not status:
if (hasattr(msg, 'status') and
msg.status == '401 UNAUTHORIZED') or\
(source.get_source_name() ==
KERBEROS and
request.method == 'GET'):
break
if status:
self.set_source(source)
self.set_current_source(source.get_source_name())
if msg is not None and 'username' in msg:
self.form._fields['email'].data = msg['username']
return status, msg
return status, msg
def login(self):
@@ -209,6 +181,13 @@ class AuthSourceManager():
current_app.logger.debug(
"Authentication and Login successfully done via source : %s" %
self.source.get_source_name())
# Set the login, logout view as per source if available
current_app.login_manager.login_view = getattr(
self.source, 'LOGIN_VIEW', 'security.login')
current_app.login_manager.logout_view = getattr(
self.source, 'LOGOUT_VIEW', 'security.logout')
return status, msg
@@ -223,7 +202,7 @@ def get_auth_sources(type):
if type in auth_sources:
return auth_sources[type]
auth_source = AuthSourceRegistry.create(type)
auth_source = AuthSourceRegistry.get(type)
if auth_source is not None:
auth_sources[type] = auth_source
@@ -236,61 +215,6 @@ def init_app(app):
auth_sources = dict()
setattr(app, '_pgadmin_auth_sources', auth_sources)
AuthSourceRegistry.load_auth_sources()
AuthSourceRegistry.load_modules(app)
return auth_sources
@blueprint.route("/kerberos/update_ticket",
endpoint="kerberos_update_ticket", methods=["GET"])
@pgCSRFProtect.exempt
@login_required
def kerberos_update_ticket():
"""
Update the kerberos ticket.
"""
from werkzeug.datastructures import Headers
headers = Headers()
authorization = request.headers.get("Authorization", None)
if authorization is None:
# Send the Negotiate header to the client
# if Kerberos ticket is not found.
headers.add('WWW-Authenticate', 'Negotiate')
return Response("Unauthorised", 401, headers)
else:
source = get_auth_sources(KERBEROS)
auth_header = authorization.split()
in_token = auth_header[1]
# Validate the Kerberos ticket
status, context = source.negotiate_start(in_token)
if status:
return Response("Ticket updated successfully.")
return Response(context, 500)
@blueprint.route("/kerberos/validate_ticket",
endpoint="kerberos_validate_ticket", methods=["GET"])
@pgCSRFProtect.exempt
@login_required
def kerberos_validate_ticket():
"""
Return the kerberos ticket lifetime left after getting the
ticket from the credential cache
"""
import gssapi
try:
del_creds = gssapi.Credentials(store={'ccache': session['KRB5CCNAME']})
creds = del_creds.acquire(store={'ccache': session['KRB5CCNAME']})
except Exception as e:
current_app.logger.exception(e)
return internal_server_error(errormsg=str(e))
return make_json_response(
data={'ticket_lifetime': creds.lifetime},
status=200
)
+4 -2
View File
@@ -10,7 +10,7 @@
"""Implements Internal Authentication"""
import six
from flask import current_app
from flask import current_app, flash
from flask_security import login_user
from abc import abstractmethod, abstractproperty
from flask_babelex import gettext
@@ -31,6 +31,8 @@ class BaseAuthentication(object):
'PASSWORD_NOT_PROVIDED': gettext('Password not provided'),
'INVALID_EMAIL': gettext('Email/Username is not valid')
}
LOGIN_VIEW = 'security.login'
LOGOUT_VIEW = 'security.logout'
@abstractmethod
def get_source_name(self):
@@ -97,7 +99,7 @@ class InternalAuthentication(BaseAuthentication):
"""User validation"""
# validate the email id first
if not validate_email(form.data['email']):
form.errors['email'] = [self.messages('INVALID_EMAIL')]
flash(self.messages('INVALID_EMAIL'), 'warning')
return False
# Flask security validation
return form.validate_on_submit()
+117 -9
View File
@@ -10,22 +10,28 @@
"""A blueprint module implementing the Spnego/Kerberos authentication."""
import base64
from os import environ, path
from os import environ, path, remove
from werkzeug.datastructures import Headers
from werkzeug.datastructures import Headers, MultiDict
from flask_babelex import gettext
from flask import Flask, request, Response, session,\
current_app, render_template, flash
from flask import request, Response, session,\
current_app, render_template, flash, url_for
from flask_security.views import _security
from flask_security.utils import logout_user
from flask_security import login_required
import config
from pgadmin.model import User
from pgadmin.tools.user_management import create_user
from pgadmin.utils.constants import KERBEROS
from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import make_json_response, internal_server_error
from flask_security.views import _security
from werkzeug.datastructures import MultiDict
from .internal import BaseAuthentication
from pgadmin.authenticate.internal import BaseAuthentication
from pgadmin.authenticate import get_auth_sources
from pgadmin.utils.csrf import pgCSRFProtect
try:
import gssapi
@@ -46,8 +52,110 @@ if config.KRB_KTNAME and config.KRB_KTNAME != '<KRB5_KEYTAB_FILE>':
environ['KRB5_KTNAME'] = config.KRB_KTNAME
class KerberosModule(PgAdminModule):
def register(self, app, options, first_registration=False):
# Do not look for the sub_modules,
# instead call blueprint.register(...) directly
super(PgAdminModule, self).register(app, options, first_registration)
def get_exposed_url_endpoints(self):
return ['kerberos.login',
'kerberos.logout',
'kerberos.update_ticket',
'kerberos.validate_ticket']
def init_app(app):
MODULE_NAME = 'kerberos'
blueprint = KerberosModule(MODULE_NAME, __name__, static_url_path='')
@blueprint.route("/login",
endpoint="login", methods=["GET"])
@pgCSRFProtect.exempt
def kerberos_login():
logout_user()
return Response(render_template("browser/kerberos_login.html",
login_url=url_for('security.login'),
))
@blueprint.route("/logout",
endpoint="logout", methods=["GET"])
@pgCSRFProtect.exempt
def kerberos_logout():
logout_user()
if 'KRB5CCNAME' in session:
# Remove the credential cache
cache_file_path = session['KRB5CCNAME'].split(":")[1]
if path.exists(cache_file_path):
remove(cache_file_path)
return Response(render_template("browser/kerberos_logout.html",
login_url=url_for('security.login'),
))
@blueprint.route("/update_ticket",
endpoint="update_ticket", methods=["GET"])
@pgCSRFProtect.exempt
@login_required
def kerberos_update_ticket():
"""
Update the kerberos ticket.
"""
from werkzeug.datastructures import Headers
headers = Headers()
authorization = request.headers.get("Authorization", None)
if authorization is None:
# Send the Negotiate header to the client
# if Kerberos ticket is not found.
headers.add('WWW-Authenticate', 'Negotiate')
return Response("Unauthorised", 401, headers)
else:
source = get_auth_sources(KERBEROS)
auth_header = authorization.split()
in_token = auth_header[1]
# Validate the Kerberos ticket
status, context = source.negotiate_start(in_token)
if status:
return Response("Ticket updated successfully.")
return Response(context, 500)
@blueprint.route("/validate_ticket",
endpoint="validate_ticket", methods=["GET"])
@pgCSRFProtect.exempt
@login_required
def kerberos_validate_ticket():
"""
Return the kerberos ticket lifetime left after getting the
ticket from the credential cache
"""
import gssapi
try:
del_creds = gssapi.Credentials(store={
'ccache': session['KRB5CCNAME']})
creds = del_creds.acquire(store={'ccache': session['KRB5CCNAME']})
except Exception as e:
current_app.logger.exception(e)
return internal_server_error(errormsg=str(e))
return make_json_response(
data={'ticket_lifetime': creds.lifetime},
status=200
)
app.register_blueprint(blueprint)
class KerberosAuthentication(BaseAuthentication):
LOGIN_VIEW = 'kerberos.login'
LOGOUT_VIEW = 'kerberos.logout'
def get_source_name(self):
return KERBEROS
@@ -85,7 +193,7 @@ class KerberosAuthentication(BaseAuthentication):
if status:
# Saving the first 15 characters of the kerberos key
# to encrypt/decrypt database password
session['kerberos_key'] = auth_header[1][0:15]
session['pass_enc_key'] = auth_header[1][0:15]
# Create user
retval = self.__auto_create_user(
str(negotiate.initiator_name))
@@ -162,7 +270,7 @@ class KerberosAuthentication(BaseAuthentication):
username = str(username)
if config.KRB_AUTO_CREATE_USER:
user = User.query.filter_by(
username=username).first()
username=username, auth_source=KERBEROS).first()
if user is None:
return create_user({
'username': username,
+176
View File
@@ -0,0 +1,176 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""A blueprint module implementing the Oauth2 authentication."""
import config
from authlib.integrations.flask_client import OAuth
from flask import current_app, url_for, session, request,\
redirect, Flask, flash
from flask_babelex import gettext
from flask_security import login_user, current_user
from flask_security.utils import get_post_logout_redirect, \
get_post_login_redirect, logout_user
from pgadmin.authenticate.internal import BaseAuthentication
from pgadmin.model import User
from pgadmin.tools.user_management import create_user
from pgadmin.utils.constants import OAUTH2
from pgadmin.utils import PgAdminModule
from pgadmin.utils.csrf import pgCSRFProtect
from pgadmin.model import db
OAUTH2_LOGOUT = 'oauth2.logout'
OAUTH2_AUTHORIZE = 'oauth2.authorize'
class Oauth2Module(PgAdminModule):
def register(self, app, options, first_registration=False):
# Do not look for the sub_modules,
# instead call blueprint.register(...) directly
super(PgAdminModule, self).register(app, options, first_registration)
def get_exposed_url_endpoints(self):
return [OAUTH2_AUTHORIZE,
OAUTH2_LOGOUT]
def init_app(app):
MODULE_NAME = 'oauth2'
blueprint = Oauth2Module(MODULE_NAME, __name__, static_url_path='')
@blueprint.route('/authorize', endpoint="authorize",
methods=['GET', 'POST'])
@pgCSRFProtect.exempt
def oauth_authorize():
auth_obj = session['auth_obj']
auth_obj.set_current_source(auth_obj.source.get_source_name())
status, msg = auth_obj.login()
if status:
session['auth_source_manager'] = auth_obj.as_dict()
if 'auth_obj' in session:
session.pop('auth_obj')
return redirect(get_post_login_redirect())
if 'auth_obj' in session:
session.pop('auth_obj')
logout_user()
flash(msg, 'danger')
return redirect(get_post_login_redirect())
@blueprint.route('/logout', endpoint="logout",
methods=['GET', 'POST'])
@pgCSRFProtect.exempt
def oauth_logout():
if not current_user.is_authenticated:
return redirect(get_post_logout_redirect())
for key in list(session.keys()):
session.pop(key)
logout_user()
return redirect(get_post_logout_redirect())
app.register_blueprint(blueprint)
app.login_manager.logout_view = OAUTH2_LOGOUT
class OAuth2Authentication(BaseAuthentication):
"""OAuth Authentication Class"""
LOGOUT_VIEW = OAUTH2_LOGOUT
oauth_obj = OAuth(Flask(__name__))
oauth2_clients = {}
oauth2_config = {}
def __init__(self):
for oauth2_config in config.OAUTH2_CONFIG:
OAuth2Authentication.oauth2_config[
oauth2_config['OAUTH2_NAME']] = oauth2_config
OAuth2Authentication.oauth2_clients[
oauth2_config['OAUTH2_NAME']
] = OAuth2Authentication.oauth_obj.register(
name=oauth2_config['OAUTH2_NAME'],
client_id=oauth2_config['OAUTH2_CLIENT_ID'],
client_secret=oauth2_config['OAUTH2_CLIENT_SECRET'],
access_token_url=oauth2_config['OAUTH2_TOKEN_URL'],
authorize_url=oauth2_config['OAUTH2_AUTHORIZATION_URL'],
api_base_url=oauth2_config['OAUTH2_API_BASE_URL'],
client_kwargs={'scope': 'email profile'}
)
def get_source_name(self):
return OAUTH2
def get_friendly_name(self):
return self.oauth2_config[self.oauth2_current_client]['OAUTH2_NAME']
def validate(self, form):
return True
def login(self, form):
profile = self.get_user_profile()
if 'email' not in profile or not profile['email']:
current_app.logger.exception(
"An email id is required to login into pgAdmin. "
"Please update your Oauth2 profile."
)
return False, gettext(
"An email id is required to login into pgAdmin. "
"Please update your Oauth2 profile.")
user, msg = self.__auto_create_user(profile)
if user:
user = db.session.query(User).filter_by(
username=profile['email'], auth_source=OAUTH2).first()
current_app.login_manager.logout_view = \
OAuth2Authentication.LOGOUT_VIEW
return login_user(user), None
return False, msg
def get_user_profile(self):
session['oauth2_token'] = self.oauth2_clients[
self.oauth2_current_client].authorize_access_token()
session['pass_enc_key'] = session['oauth2_token']['access_token']
resp = self.oauth2_clients[self.oauth2_current_client].get(
self.oauth2_config[
self.oauth2_current_client]['OAUTH2_USERINFO_ENDPOINT'],
token=session['oauth2_token']
)
resp.raise_for_status()
return resp.json()
def authenticate(self, form):
self.oauth2_current_client = request.form['oauth2_button']
redirect_url = url_for(OAUTH2_AUTHORIZE, _external=True)
if self.oauth2_current_client not in self.oauth2_clients:
return False, gettext(
"Please set the configuration parameters properly.")
return False, self.oauth2_clients[
self.oauth2_current_client].authorize_redirect(redirect_url)
def __auto_create_user(self, resp):
if config.OAUTH2_AUTO_CREATE_USER:
user = User.query.filter_by(username=resp['email'],
auth_source=OAUTH2).first()
if not user:
return create_user({
'username': resp['email'],
'email': resp['email'],
'role': 2,
'active': True,
'auth_source': OAUTH2
})
return True, {'username': resp['email']}
+4 -51
View File
@@ -10,56 +10,9 @@
"""External Authentication Registry."""
from flask_babelex import gettext
from abc import ABCMeta
from pgadmin.utils.dynamic_registry import create_registry_metaclass
def _decorate_cls_name(module_name):
length = len(__package__) + 1
if len(module_name) > length and module_name.startswith(__package__):
return module_name[length:]
return module_name
class AuthSourceRegistry(ABCMeta):
registry = None
auth_sources = dict()
def __init__(self, name, bases, d):
# Register this type of auth_sources, based on the module name
# Avoid registering the BaseAuthentication itself
AuthSourceRegistry.registry[_decorate_cls_name(d['__module__'])] = self
ABCMeta.__init__(self, name, bases, d)
@classmethod
def create(cls, name, **kwargs):
if name in AuthSourceRegistry.auth_sources:
return AuthSourceRegistry.auth_sources[name]
if name in AuthSourceRegistry.registry:
AuthSourceRegistry.auth_sources[name] = \
(AuthSourceRegistry.registry[name])(**kwargs)
return AuthSourceRegistry.auth_sources[name]
raise NotImplementedError(
gettext(
"Authentication source '{0}' has not been implemented."
).format(name)
)
@classmethod
def load_auth_sources(cls):
# Initialize the registry only if it has not yet been initialized
if AuthSourceRegistry.registry is None:
AuthSourceRegistry.registry = dict()
from importlib import import_module
from werkzeug.utils import find_modules
for module_name in find_modules(__package__, True):
import_module(module_name)
AuthSourceRegistry = create_registry_metaclass(
"AuthSourceRegistry", __package__, decorate_as_module=True
)
+11 -2
View File
@@ -1,10 +1,19 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import url_for from 'sources/url_for';
import userInfo from 'pgadmin.user_management.current_user';
import pgConst from 'pgadmin.browser.constants';
function fetch_ticket() {
// Fetch the Kerberos Updated ticket through SPNEGO
return fetch(url_for('authenticate.kerberos_update_ticket')
return fetch(url_for('kerberos.update_ticket')
)
.then(function(response){
if (response.status >= 200 && response.status < 300) {
@@ -18,7 +27,7 @@ function fetch_ticket() {
function fetch_ticket_lifetime () {
// Fetch the Kerberos ticket lifetime left
return fetch(url_for('authenticate.kerberos_validate_ticket')
return fetch(url_for('kerberos.validate_ticket')
)
.then(
function(response){
+41 -19
View File
@@ -32,7 +32,7 @@ from flask_security.recoverable import reset_password_token_status, \
from flask_security.signals import reset_password_instructions_sent
from flask_security.utils import config_value, do_flash, get_url, \
get_message, slash_url_suffix, login_user, send_mail, logout_user
from flask_security.views import _security, _commit, _ctx
from flask_security.views import _security, view_commit, _ctx
from werkzeug.datastructures import MultiDict
import config
@@ -50,7 +50,8 @@ from pgadmin.utils.master_password import validate_master_password, \
set_crypt_key, process_masterpass_disabled
from pgadmin.model import User
from pgadmin.utils.constants import MIMETYPE_APP_JS, PGADMIN_NODE,\
INTERNAL, KERBEROS, LDAP
INTERNAL, KERBEROS, LDAP, QT_DEFAULT_PLACEHOLDER, OAUTH2
from pgadmin.authenticate import AuthSourceManager
try:
from flask_security.views import default_render_json
@@ -342,6 +343,7 @@ class BrowserModule(PgAdminModule):
list: a list of url endpoints exposed to the client.
"""
return [BROWSER_INDEX, 'browser.nodes',
'browser.check_corrupted_db_file',
'browser.check_master_password',
'browser.set_master_password',
'browser.reset_master_password',
@@ -605,14 +607,8 @@ class BrowserPluginModule(PgAdminModule):
def _get_logout_url():
if config.SERVER_MODE and\
session['_auth_source_manager_obj']['current_source'] == \
KERBEROS:
return '{0}?next={1}'.format(url_for(
'authenticate.kerberos_logout'), url_for(BROWSER_INDEX))
return '{0}?next={1}'.format(
url_for('security.logout'), url_for(BROWSER_INDEX))
url_for(current_app.login_manager.logout_view), url_for(BROWSER_INDEX))
def _get_supported_browser():
@@ -746,10 +742,10 @@ def index():
if len(config.AUTHENTICATION_SOURCES) == 1\
and INTERNAL in config.AUTHENTICATION_SOURCES:
auth_only_internal = True
auth_source = session['_auth_source_manager_obj'][
auth_source = session['auth_source_manager'][
'source_friendly_name']
if session['_auth_source_manager_obj']['current_source'] == KERBEROS:
if not config.MASTER_PASSWORD_REQUIRED and 'pass_enc_key' in session:
session['allow_save_password'] = False
response = Response(render_template(
@@ -851,7 +847,10 @@ def utils():
app_version_int=config.APP_VERSION_INT,
pg_libpq_version=pg_libpq_version,
support_ssh_tunnel=config.SUPPORT_SSH_TUNNEL,
logout_url=_get_logout_url()
logout_url=_get_logout_url(),
platform=sys.platform,
qt_default_placeholder=QT_DEFAULT_PLACEHOLDER,
enable_psql=config.ENABLE_PSQL
),
200, {'Content-Type': MIMETYPE_APP_JS})
@@ -872,7 +871,8 @@ def app_constants():
render_template('browser/js/constants.js',
INTERNAL=INTERNAL,
LDAP=LDAP,
KERBEROS=KERBEROS),
KERBEROS=KERBEROS,
OAUTH2=OAUTH2),
200, {'Content-Type': MIMETYPE_APP_JS}
)
@@ -949,6 +949,19 @@ def form_master_password_response(existing=True, present=False, errmsg=None):
})
@blueprint.route("/check_corrupted_db_file",
endpoint="check_corrupted_db_file", methods=["GET"])
def check_corrupted_db_file():
"""
Get the corrupted database file path.
"""
file_location = os.environ['CORRUPTED_DB_BACKUP_FILE'] \
if 'CORRUPTED_DB_BACKUP_FILE' in os.environ else ''
# reset the corrupted db file path in env.
os.environ['CORRUPTED_DB_BACKUP_FILE'] = ''
return make_json_response(data=file_location)
@blueprint.route("/master_password", endpoint="check_master_password",
methods=["GET"])
def check_master_password():
@@ -987,8 +1000,10 @@ def set_master_password():
data = json.loads(data)
# Master password is not applicable for server mode
if not config.SERVER_MODE and config.MASTER_PASSWORD_REQUIRED:
# Enable master password if oauth is used
if not config.SERVER_MODE or OAUTH2 in config.AUTHENTICATION_SOURCES \
or KERBEROS in config.AUTHENTICATION_SOURCES \
and config.MASTER_PASSWORD_REQUIRED:
# if master pass is set previously
if current_user.masterpass_check is not None and \
data.get('button_click') and \
@@ -1025,7 +1040,7 @@ def set_master_password():
existing=True,
present=False,
)
elif not get_crypt_key()[0]:
elif not get_crypt_key()[1]:
error_message = None
if data.get('button_click') and data.get('password') == '':
# If user attempted to enter a blank password, then throw error
@@ -1117,7 +1132,8 @@ if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
if form.validate_on_submit():
try:
change_user_password(current_user, form.new_password.data)
change_user_password(current_user._get_current_object(),
form.new_password.data)
except SOCKETErrorException as e:
# Handle socket errors which are not covered by SMTPExceptions.
logging.exception(str(e), exc_info=True)
@@ -1143,7 +1159,7 @@ if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
has_error = True
if request.json is None and not has_error:
after_this_request(_commit)
after_this_request(view_commit)
do_flash(*get_message('PASSWORD_CHANGE'))
old_key = get_crypt_key()[1]
@@ -1309,9 +1325,15 @@ if hasattr(config, 'SECURITY_RECOVERABLE') and config.SECURITY_RECOVERABLE:
has_error = True
if not has_error:
after_this_request(_commit)
after_this_request(view_commit)
auth_obj = AuthSourceManager(form, [INTERNAL])
session['_auth_source_manager_obj'] = auth_obj.as_dict()
do_flash(*get_message('PASSWORD_RESET'))
login_user(user)
auth_obj = AuthSourceManager(form, [INTERNAL])
session['auth_source_manager'] = auth_obj.as_dict()
return redirect(get_url(_security.post_reset_view) or
get_url(_security.post_login_view))
@@ -6,10 +6,12 @@
# This software is released under the PostgreSQL Licence
#
##########################################################################
import sys
from flask_babelex import gettext
from pgadmin.utils.constants import PREF_LABEL_DISPLAY,\
PREF_LABEL_KEYBOARD_SHORTCUTS, PREF_LABEL_TABS_SETTINGS, \
PREF_LABEL_OPTIONS
PREF_LABEL_OPTIONS, QT_DEFAULT_PLACEHOLDER
from flask_security import current_user
import config
LOCK_LAYOUT_LEVEL = {
@@ -468,7 +470,7 @@ def register_browser_preferences(self):
self.qt_tab_title = self.preference.register(
'tab_settings', 'qt_tab_title_placeholder',
gettext("Query tool tab title"),
'text', '%DATABASE%/%USERNAME%@%SERVER%',
'text', QT_DEFAULT_PLACEHOLDER,
category_label=PREF_LABEL_DISPLAY,
help_str=gettext(
'Supported placeholders are %DATABASE%, %USERNAME%, and %SERVER%. '
@@ -504,17 +506,27 @@ def register_browser_preferences(self):
)
)
ope_new_tab_options = [
{'label': gettext('Query Tool'), 'value': 'qt'},
{'label': gettext('Debugger'), 'value': 'debugger'},
{'label': gettext('Schema Diff'), 'value': 'schema_diff'},
{'label': gettext('ERD Tool'), 'value': 'erd_tool'}]
# Allow psq tool to open in new browser tab if ENABLE_PSQL is set to True
if config.ENABLE_PSQL:
ope_new_tab_options.append(
{'label': gettext('PSQL Tool'), 'value': 'psql_tool'})
self.open_in_new_tab = self.preference.register(
'tab_settings', 'new_browser_tab_open',
gettext("Open in new browser tab"), 'select2', None,
category_label=PREF_LABEL_OPTIONS,
options=[{'label': gettext('Query Tool'), 'value': 'qt'},
{'label': gettext('Debugger'), 'value': 'debugger'},
{'label': gettext('Schema Diff'), 'value': 'schema_diff'},
{'label': gettext('ERD Tool'), 'value': 'erd_tool'}],
help_str=gettext('Select Query Tool, Debugger, or Schema Diff from '
'the drop-down to set open in new browser tab for '
'that particular module.'),
options=ope_new_tab_options,
help_str=gettext(
'Select Query Tool, Debugger, Schema Diff, ERD Tool '
'or PSQL Tool from the drop-down to set '
'open in new browser tab for that particular module.'
),
select2={
'multiple': True, 'allowClear': False,
'tags': True, 'first_empty': False,
@@ -523,3 +535,18 @@ def register_browser_preferences(self):
'placeholder': gettext('Select open new tab...')
}
)
# Set PSQL tool tab title if ENABLE_PSQL is set to True
if config.ENABLE_PSQL:
self.psql_tab_title = self.preference.register(
'tab_settings', 'psql_tab_title_placeholder',
gettext("PSQL tool tab title"),
'text', '%DATABASE%/%USERNAME%@%SERVER%',
category_label=PREF_LABEL_DISPLAY,
help_str=gettext(
'Supported placeholders are %DATABASE%, %USERNAME%, '
'and %SERVER%. Users can provide any string with or without'
' placeholders of their choice. The blank title will be revert'
' back to the default title with placeholders.'
)
)
@@ -34,6 +34,7 @@ from pgadmin.utils.constants import UNAUTH_REQ, MIMETYPE_APP_JS, \
SERVER_CONNECTION_CLOSED
from sqlalchemy import or_
from pgadmin.utils.preferences import Preferences
from .... import socketio as sio
def has_any(data, keys):
@@ -1499,6 +1500,13 @@ class ServerNode(PGChildNodeView):
# Release Connection
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
# Check if any psql terminal is running for the current disconnecting
# server. If any terminate the psql tool connection.
if 'sid_soid_mapping' in current_app.config and str(sid) in \
current_app.config['sid_soid_mapping']:
if str(sid) in current_app.config['sid_soid_mapping']:
for i in current_app.config['sid_soid_mapping'][str(sid)]:
sio.emit('disconnect-psql', namespace='/pty', to=i)
status = manager.release()
@@ -0,0 +1,4 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__1_$%{}[]()&*^!@""'`\/#" SET DEFAULT 'changed default value';
GRANT SELECT("col__1_$%{}[]()&*^!@""'`\/#") ON testschema."table_2_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
@@ -0,0 +1,11 @@
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__1_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__1_$%{}[]()&*^!@""'`\/#" text COLLATE pg_catalog."default" DEFAULT 'changed default value'::text;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
GRANT SELECT("col__1_$%{}[]()&*^!@""'`\/#") ON testschema."table_2_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
@@ -0,0 +1,7 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__2_$%{}[]()&*^!@""'`\/#" TYPE time(6) with time zone ;
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__2_$%{}[]()&*^!@""'`\/#" SET NOT NULL;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
IS 'test comment modification';
@@ -0,0 +1,9 @@
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__2_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__2_$%{}[]()&*^!@""'`\/#" time(6) with time zone NOT NULL DEFAULT now();
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
IS 'test comment modification';
@@ -0,0 +1,3 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
SET (n_distinct=2);
@@ -0,0 +1,13 @@
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__3_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__3_$%{}[]()&*^!@""'`\/#" integer[] NOT NULL;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
IS 'comment';
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
SET (n_distinct=2);
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50, None) COLLATE pg_catalog."C" DEFAULT None;
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50) COLLATE pg_catalog."C";
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_6_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL GENERATED BY DEFAULT AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 10 CACHE 1 );
ADD COLUMN "col_6_$%{}[]()&*^!@""'`\/#" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 10 CACHE 1 );
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_6_$%{}[]()&*^!@""'`\/#"
IS 'demo comments';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_1_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL DEFAULT 1;
ADD COLUMN "col_1_$%{}[]()&*^!@""'`\/#" bigint NOT NULL DEFAULT 1;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_1_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_3_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL GENERATED ALWAYS AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
ADD COLUMN "col_3_$%{}[]()&*^!@""'`\/#" bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_3_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_5_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL GENERATED BY DEFAULT AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
ADD COLUMN "col_5_$%{}[]()&*^!@""'`\/#" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_5_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -0,0 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__1_$%{}[]()&*^!@""'`\/#" text DEFAULT 'xyz';
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
@@ -0,0 +1,9 @@
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__1_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__1_$%{}[]()&*^!@""'`\/#" text COLLATE pg_catalog."default" DEFAULT 'xyz'::text;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
@@ -0,0 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__2_$%{}[]()&*^!@""'`\/#" time(4) with time zone DEFAULT now();
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
@@ -0,0 +1,9 @@
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__2_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__2_$%{}[]()&*^!@""'`\/#" time(4) with time zone DEFAULT now();
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
@@ -0,0 +1,9 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__3_$%{}[]()&*^!@""'`\/#" integer[] NOT NULL;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
IS 'comment';
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
SET (n_distinct=1);
@@ -0,0 +1,13 @@
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__3_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__3_$%{}[]()&*^!@""'`\/#" integer[] NOT NULL;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
IS 'comment';
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
SET (n_distinct=1);
@@ -26,8 +26,8 @@
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": null,
"attprecision": null,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"defval": "1"
@@ -138,10 +138,9 @@
"is_primary_key": false,
"attnotnull": false,
"attlen": "50",
"attprecision": null,
"attprecision": "",
"attoptions": [],
"seclabels": [],
"defval": null
"seclabels": []
},
"expected_sql_file": "create_column_char.sql",
"expected_msql_file": "create_column_char.msql"
@@ -211,8 +210,8 @@
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": null,
"attprecision": null,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"attidentity": "a",
@@ -398,8 +397,8 @@
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": null,
"attprecision": null,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"attidentity": "d",
@@ -468,8 +467,8 @@
"description": "demo comments",
"is_primary_key": false,
"attnotnull": true,
"attlen": null,
"attprecision": null,
"attlen": "",
"attprecision": "",
"attidentity": "d",
"seqincrement": "1",
"seqstart": "1",
@@ -526,6 +525,174 @@
"data": {
"name": "col_6_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create Column with text & default value",
"endpoint": "NODE-column.obj",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql",
"data": {
"name": "col__1_$%{}[]()&*^!@\"'`\\/#",
"cltype": "text",
"attacl": [],
"description": "test comment",
"is_primary_key": false,
"attnotnull": false,
"attlen": "",
"attprecision": "",
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": [],
"defval": "'xyz'"
},
"expected_sql_file": "create_column_text_with_default_value.sql",
"expected_msql_file": "create_column_text_with_default_value.msql"
},
{
"type": "alter",
"name": "Alter Column with text & update default value",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql_id",
"data": {
"name": "col__1_$%{}[]()&*^!@\"'`\\/#",
"defval": "'changed default value'",
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_text_with_default_value.sql",
"expected_msql_file": "alter_column_text_with_default_value.msql"
},
{
"type": "delete",
"name": "Drop Column with identity (ALWAYS)",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"data": {
"name": "col__1_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create Column with time with time zone & default value using function",
"endpoint": "NODE-column.obj",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql",
"data": {
"name": "col__2_$%{}[]()&*^!@\"'`\\/#",
"cltype": "time with time zone",
"attacl": [],
"description": "test comment",
"min_val_attlen": 0,
"max_val_attlen": 6,
"is_primary_key": false,
"attnotnull": false,
"attlen": "4",
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": [],
"defval": "now()"
},
"expected_sql_file": "create_column_timestamp_with_default_value_using_function.sql",
"expected_msql_file": "create_column_timestamp_with_default_value_using_function.msql"
},
{
"type": "alter",
"name": "Alter Column with time with time zone & update length",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql_id",
"data": {
"name": "col__2_$%{}[]()&*^!@\"'`\\/#",
"attlen": "6",
"attnotnull": true,
"description": "test comment modification"
},
"expected_sql_file": "alter_column_timestamp_with_default_value_using_function.sql",
"expected_msql_file": "alter_column_timestamp_with_default_value_using_function.msql"
},
{
"type": "delete",
"name": "Drop Column with identity (ALWAYS)",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"data": {
"name": "col__2_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create Column with interger_array and options",
"endpoint": "NODE-column.obj",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql",
"data": {
"name": "col__3_$%{}[]()&*^!@\"'`\\/#",
"cltype": "integer[]",
"attacl": [],
"description": "comment",
"is_primary_key": false,
"attnotnull": true,
"attlen": "",
"attprecision": "",
"attidentity": "a",
"colconstype": "n",
"attoptions": [
{
"name": "n_distinct",
"value": "1"
}
],
"seclabels": []
},
"expected_sql_file": "create_column_with_interger_array_and_options.sql",
"expected_msql_file": "create_column_with_interger_array_and_options.msql"
},
{
"type": "alter",
"name": "Alter Column with interger_array and options",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql_id",
"data": {
"name": "col__3_$%{}[]()&*^!@\"'`\\/#",
"attoptions": {
"changed": [
{
"name": "n_distinct",
"value": "2"
}
]
}
},
"expected_sql_file": "alter_column_with_interger_array_and_options.sql",
"expected_msql_file": "alter_column_with_interger_array_and_options.msql"
},
{
"type": "delete",
"name": "Drop Column with identity (ALWAYS)",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"data": {
"name": "col__3_$%{}[]()&*^!@\"'`\\/#"
}
}
]
}
@@ -2,7 +2,7 @@ ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
RENAME "col_2_$%{}[]()&*^!@""'`\/#" TO "new_col_2_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "new_col_2_$%{}[]()&*^!@""'`\/#" TYPE character(None) COLLATE pg_catalog."C";
ALTER COLUMN "new_col_2_$%{}[]()&*^!@""'`\/#" TYPE character COLLATE pg_catalog."C";
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "new_col_2_$%{}[]()&*^!@""'`\/#" SET STATISTICS 5;
@@ -12,4 +12,4 @@ ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."new_col_2_$%{}[]()&*^!@""'`\/#"
IS 'Comment for alter';
GRANT INSERT("new_col_2_$%{}[]()&*^!@""'`\/#"), SELECT("new_col_2_$%{}[]()&*^!@""'`\/#"), REFERENCES("new_col_2_$%{}[]()&*^!@""'`\/#") ON testschema."table_3_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
GRANT INSERT("new_col_2_$%{}[]()&*^!@""'`\/#"), SELECT("new_col_2_$%{}[]()&*^!@""'`\/#"), REFERENCES("new_col_2_$%{}[]()&*^!@""'`\/#") ON testschema."table_3_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
@@ -0,0 +1,4 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__1_$%{}[]()&*^!@""'`\/#" SET DEFAULT 'changed default value';
GRANT SELECT("col__1_$%{}[]()&*^!@""'`\/#") ON testschema."table_3_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
@@ -0,0 +1,11 @@
-- Column: testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__1_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__1_$%{}[]()&*^!@""'`\/#" text COLLATE pg_catalog."default" DEFAULT 'changed default value'::text;
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
GRANT SELECT("col__1_$%{}[]()&*^!@""'`\/#") ON testschema."table_3_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
@@ -0,0 +1,7 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__2_$%{}[]()&*^!@""'`\/#" TYPE time(6) with time zone ;
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__2_$%{}[]()&*^!@""'`\/#" SET NOT NULL;
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
IS 'test comment modification';
@@ -0,0 +1,9 @@
-- Column: testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__2_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__2_$%{}[]()&*^!@""'`\/#" time(6) with time zone NOT NULL DEFAULT now();
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
IS 'test comment modification';
@@ -0,0 +1,3 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
SET (n_distinct=2);
@@ -0,0 +1,13 @@
-- Column: testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__3_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__3_$%{}[]()&*^!@""'`\/#" integer[] NOT NULL;
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
IS 'comment';
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
SET (n_distinct=2);
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50, None) COLLATE pg_catalog."C" DEFAULT None;
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50) COLLATE pg_catalog."C";
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_1_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL DEFAULT 1;
ADD COLUMN "col_1_$%{}[]()&*^!@""'`\/#" bigint NOT NULL DEFAULT 1;
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col_1_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_4_$%{}[]()&*^!@""'`\/#" bigint(None, None) GENERATED ALWAYS AS (1 + 2 + 3) STORED;
ADD COLUMN "col_4_$%{}[]()&*^!@""'`\/#" bigint GENERATED ALWAYS AS (1 + 2 + 3) STORED;
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col_4_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_8_$%{}[]()&*^!@""'`\/#" bigint(None, None) GENERATED ALWAYS AS (dummy1 + dummy2) STORED;
ADD COLUMN "col_8_$%{}[]()&*^!@""'`\/#" bigint GENERATED ALWAYS AS (dummy1 + dummy2) STORED;
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col_8_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_3_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL GENERATED ALWAYS AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
ADD COLUMN "col_3_$%{}[]()&*^!@""'`\/#" bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col_3_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_9_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL GENERATED BY DEFAULT AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
ADD COLUMN "col_9_$%{}[]()&*^!@""'`\/#" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col_9_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -0,0 +1,5 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__1_$%{}[]()&*^!@""'`\/#" text DEFAULT 'xyz';
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
@@ -0,0 +1,9 @@
-- Column: testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__1_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__1_$%{}[]()&*^!@""'`\/#" text COLLATE pg_catalog."default" DEFAULT 'xyz'::text;
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
@@ -0,0 +1,5 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__2_$%{}[]()&*^!@""'`\/#" time(4) with time zone DEFAULT now();
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
@@ -0,0 +1,9 @@
-- Column: testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__2_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__2_$%{}[]()&*^!@""'`\/#" time(4) with time zone DEFAULT now();
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
@@ -0,0 +1,9 @@
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__3_$%{}[]()&*^!@""'`\/#" integer[] NOT NULL;
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
IS 'comment';
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
SET (n_distinct=1);
@@ -0,0 +1,13 @@
-- Column: testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__3_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__3_$%{}[]()&*^!@""'`\/#" integer[] NOT NULL;
COMMENT ON COLUMN testschema."table_3_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
IS 'comment';
ALTER TABLE testschema."table_3_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
SET (n_distinct=1);
@@ -22,15 +22,15 @@
"data": {
"name": "col_1_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for create",
"cltype":"bigint",
"attacl":[],
"is_primary_key":false,
"attnotnull":true,
"attlen":null,
"attprecision":null,
"attoptions":[],
"seclabels":[],
"defval":"1"
"cltype": "bigint",
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"defval": "1"
},
"expected_sql_file": "create_column_int.sql",
"expected_msql_file": "create_column_int.msql"
@@ -45,8 +45,37 @@
"attnum": 1,
"name": "new_col_1_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for alter",
"cltype":"real",
"attacl":{"added":[{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false},{"privilege_type":"w","privilege":true,"with_grant":false},{"privilege_type":"x","privilege":true,"with_grant":false}]}]}
"cltype": "real",
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "w",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_int.sql",
"expected_msql_file": "alter_column_int.msql"
@@ -60,7 +89,26 @@
"data": {
"attnum": 1,
"name": "new_col_1_$%{}[]()&*^!@\"'`\\/#",
"attacl":{"changed":[{"grantee":"postgres", "grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false}]}]}
"attacl": {
"changed": [
{
"grantee": "postgres",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_alt_privilege.sql",
"expected_msql_file": "alter_column_alt_privilege.msql"
@@ -83,16 +131,15 @@
"data": {
"name": "col_2_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for create",
"cltype":"character varying",
"cltype": "character varying",
"collspcname": "pg_catalog.\"C\"",
"attacl":[],
"is_primary_key":false,
"attnotnull":false,
"attlen":"50",
"attprecision":null,
"attoptions":[],
"seclabels":[],
"defval":null
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": "50",
"attprecision": "",
"attoptions": [],
"seclabels": []
},
"expected_sql_file": "create_column_char.sql",
"expected_msql_file": "create_column_char.msql"
@@ -106,12 +153,36 @@
"data": {
"attnum": 2,
"name": "new_col_2_$%{}[]()&*^!@\"'`\\/#",
"attlen": null,
"attlen": "",
"attstattarget": "5",
"attstorage": "p",
"description": "Comment for alter",
"cltype":"character",
"attacl":{"added":[{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false},{"privilege_type":"x","privilege":true,"with_grant":false}]}]}
"cltype": "character",
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_char.sql",
"expected_msql_file": "alter_column_char.msql"
@@ -134,22 +205,22 @@
"data": {
"name": "col_3_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for create",
"cltype":"bigint",
"attacl":[],
"is_primary_key":false,
"attnotnull":true,
"attlen":null,
"attprecision":null,
"attoptions":[],
"seclabels":[],
"attidentity":"a",
"seqincrement":"1",
"seqstart":"1",
"seqmin":"1",
"seqmax":"99999",
"seqcache":"10",
"seqcycle":true,
"colconstype":"i"
"cltype": "bigint",
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"attidentity": "a",
"seqincrement": "1",
"seqstart": "1",
"seqmin": "1",
"seqmax": "99999",
"seqcache": "10",
"seqcycle": true,
"colconstype": "i"
},
"expected_sql_file": "create_column_int_identity.sql",
"expected_msql_file": "create_column_int_identity.msql"
@@ -164,7 +235,31 @@
"attnum": 3,
"name": "new_col_3_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for alter",
"attacl":{"added":[{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false},{"privilege_type":"x","privilege":true,"with_grant":false}]}]}
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_identity.sql",
"expected_msql_file": "alter_column_identity.msql"
@@ -200,17 +295,17 @@
"data": {
"name": "col_4_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for create",
"cltype":"bigint",
"attacl":[],
"is_primary_key":false,
"attnotnull":false,
"attlen":null,
"attprecision":null,
"attidentity":"a",
"colconstype":"g",
"genexpr":"1 + 2 + 3",
"attoptions":[],
"seclabels":[]
"cltype": "bigint",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": "",
"attprecision": "",
"attidentity": "a",
"colconstype": "g",
"genexpr": "1 + 2 + 3",
"attoptions": [],
"seclabels": []
},
"expected_sql_file": "create_column_int_generated.sql",
"expected_msql_file": "create_column_int_generated.msql"
@@ -225,7 +320,31 @@
"attnum": 4,
"name": "new_col_4_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for alter",
"attacl":{"added":[{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false},{"privilege_type":"x","privilege":true,"with_grant":false}]}]}
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_generated.sql",
"expected_msql_file": "alter_column_generated.msql"
@@ -248,17 +367,22 @@
"data": {
"name": "col_5_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for create",
"min_val":0,
"max_val":1000,
"cltype":"numeric",
"attacl":[],
"is_primary_key":false,
"attnotnull":true,
"attlen":"10",
"attprecision":"5",
"attidentity":"a",
"attoptions":[{"name":"n_distinct","value":"1"}],
"seclabels":[]
"min_val": 0,
"max_val": 1000,
"cltype": "numeric",
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": "10",
"attprecision": "5",
"attidentity": "a",
"attoptions": [
{
"name": "n_distinct",
"value": "1"
}
],
"seclabels": []
},
"expected_sql_file": "create_column_numeric.sql",
"expected_msql_file": "create_column_numeric.msql"
@@ -272,10 +396,39 @@
"data": {
"name": "new_col_5_$%{}[]()&*^!@\"'`\\/#",
"attnum": 5,
"attlen":"15",
"attprecision":"6",
"attlen": "15",
"attprecision": "6",
"description": "Comment for alter",
"attacl":{"added":[{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false},{"privilege_type":"w","privilege":true,"with_grant":false},{"privilege_type":"x","privilege":true,"with_grant":false}]}]}
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "w",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_numeric.sql",
"expected_msql_file": "alter_column_numeric.msql"
@@ -288,7 +441,7 @@
"msql_endpoint": "NODE-column.msql_id",
"data": {
"attnum": 3,
"attlen":""
"attlen": ""
},
"expected_sql_file": "alter_column_remove_length.sql",
"expected_msql_file": "alter_column_remove_length.msql"
@@ -302,7 +455,6 @@
"name": "new_col_5_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create Dummy Column (Integer/Numeric type)",
@@ -312,15 +464,15 @@
"data": {
"name": "dummy1",
"description": "Comment for create",
"cltype":"bigint",
"attacl":[],
"is_primary_key":false,
"attnotnull":true,
"attlen":null,
"attprecision":null,
"attoptions":[],
"seclabels":[],
"defval":"1"
"cltype": "bigint",
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"defval": "1"
}
},
{
@@ -332,15 +484,15 @@
"data": {
"name": "dummy2",
"description": "Comment for create",
"cltype":"bigint",
"attacl":[],
"is_primary_key":false,
"attnotnull":true,
"attlen":null,
"attprecision":null,
"attoptions":[],
"seclabels":[],
"defval":"1"
"cltype": "bigint",
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"defval": "1"
}
},
{
@@ -352,17 +504,17 @@
"data": {
"name": "col_8_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for create",
"cltype":"bigint",
"attacl":[],
"is_primary_key":false,
"attnotnull":false,
"attlen":null,
"attprecision":null,
"attidentity":"a",
"colconstype":"g",
"genexpr":"dummy1 + dummy2",
"attoptions":[],
"seclabels":[]
"cltype": "bigint",
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": "",
"attprecision": "",
"attidentity": "a",
"colconstype": "g",
"genexpr": "dummy1 + dummy2",
"attoptions": [],
"seclabels": []
},
"expected_sql_file": "create_column_int_generated_with_existing_columns.sql",
"expected_msql_file": "create_column_int_generated_with_existing_columns.msql"
@@ -376,9 +528,33 @@
"data": {
"attnum": 8,
"name": "new_col_8_$%{}[]()&*^!@\"'`\\/#",
"genexpr":"dummy1 - dummy2",
"genexpr": "dummy1 - dummy2",
"description": "Comment for alter",
"attacl":{"added":[{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false},{"privilege_type":"x","privilege":true,"with_grant":false}]}]}
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_generated_with_existing_columns.sql",
"expected_msql_file": "alter_column_generated_with_existing_columns.msql"
@@ -392,7 +568,6 @@
"name": "new_col_8_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create Column with identity (Generated by default)",
@@ -402,22 +577,22 @@
"data": {
"name": "col_9_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for create",
"cltype":"bigint",
"attacl":[],
"is_primary_key":false,
"attnotnull":true,
"attlen":null,
"attprecision":null,
"attoptions":[],
"seclabels":[],
"attidentity":"d",
"seqincrement":"1",
"seqstart":"1",
"seqmin":"1",
"seqmax":"99999",
"seqcache":"10",
"seqcycle":true,
"colconstype":"i"
"cltype": "bigint",
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"attidentity": "d",
"seqincrement": "1",
"seqstart": "1",
"seqmin": "1",
"seqmax": "99999",
"seqcache": "10",
"seqcycle": true,
"colconstype": "i"
},
"expected_sql_file": "create_column_int_identity_by_default.sql",
"expected_msql_file": "create_column_int_identity_by_default.msql"
@@ -432,11 +607,11 @@
"attnum": 9,
"name": "new_col_9_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for alter",
"seqincrement":"2",
"seqmax":"200",
"seqcache":"2",
"seqcycle":true,
"seqmin":"1"
"seqincrement": "2",
"seqmax": "200",
"seqcache": "2",
"seqcycle": true,
"seqmin": "1"
},
"expected_sql_file": "alter_column_identity_by_default.sql",
"expected_msql_file": "alter_column_identity_by_default.msql"
@@ -534,6 +709,174 @@
"data": {
"name": "col_6_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create Column with text & default value",
"endpoint": "NODE-column.obj",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql",
"data": {
"name": "col__1_$%{}[]()&*^!@\"'`\\/#",
"cltype": "text",
"attacl": [],
"description": "test comment",
"is_primary_key": false,
"attnotnull": false,
"attlen": "",
"attprecision": "",
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": [],
"defval": "'xyz'"
},
"expected_sql_file": "create_column_text_with_default_value.sql",
"expected_msql_file": "create_column_text_with_default_value.msql"
},
{
"type": "alter",
"name": "Alter Column with text & update default value",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql_id",
"data": {
"name": "col__1_$%{}[]()&*^!@\"'`\\/#",
"defval": "'changed default value'",
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_text_with_default_value.sql",
"expected_msql_file": "alter_column_text_with_default_value.msql"
},
{
"type": "delete",
"name": "Drop Column with identity (ALWAYS)",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"data": {
"name": "col__1_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create Column with time with time zone & default value using function",
"endpoint": "NODE-column.obj",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql",
"data": {
"name": "col__2_$%{}[]()&*^!@\"'`\\/#",
"cltype": "time with time zone",
"attacl": [],
"description": "test comment",
"min_val_attlen": 0,
"max_val_attlen": 6,
"is_primary_key": false,
"attnotnull": false,
"attlen": "4",
"attprecision": null,
"attidentity": "a",
"colconstype": "n",
"attoptions": [],
"seclabels": [],
"defval": "now()"
},
"expected_sql_file": "create_column_timestamp_with_default_value_using_function.sql",
"expected_msql_file": "create_column_timestamp_with_default_value_using_function.msql"
},
{
"type": "alter",
"name": "Alter Column with time with time zone & update length",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql_id",
"data": {
"name": "col__2_$%{}[]()&*^!@\"'`\\/#",
"attlen": "6",
"attnotnull": true,
"description": "test comment modification"
},
"expected_sql_file": "alter_column_timestamp_with_default_value_using_function.sql",
"expected_msql_file": "alter_column_timestamp_with_default_value_using_function.msql"
},
{
"type": "delete",
"name": "Drop Column with identity (ALWAYS)",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"data": {
"name": "col__2_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create Column with interger_array and options",
"endpoint": "NODE-column.obj",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql",
"data": {
"name": "col__3_$%{}[]()&*^!@\"'`\\/#",
"cltype": "integer[]",
"attacl": [],
"description": "comment",
"is_primary_key": false,
"attnotnull": true,
"attlen": "",
"attprecision": "",
"attidentity": "a",
"colconstype": "n",
"attoptions": [
{
"name": "n_distinct",
"value": "1"
}
],
"seclabels": []
},
"expected_sql_file": "create_column_with_interger_array_and_options.sql",
"expected_msql_file": "create_column_with_interger_array_and_options.msql"
},
{
"type": "alter",
"name": "Alter Column with interger_array and options",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"msql_endpoint": "NODE-column.msql_id",
"data": {
"name": "col__3_$%{}[]()&*^!@\"'`\\/#",
"attoptions": {
"changed": [
{
"name": "n_distinct",
"value": "2"
}
]
}
},
"expected_sql_file": "alter_column_with_interger_array_and_options.sql",
"expected_msql_file": "alter_column_with_interger_array_and_options.msql"
},
{
"type": "delete",
"name": "Drop Column with identity (ALWAYS)",
"endpoint": "NODE-column.obj_id",
"sql_endpoint": "NODE-column.sql_id",
"data": {
"name": "col__3_$%{}[]()&*^!@\"'`\\/#"
}
}
]
}
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_1_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50, None) COLLATE pg_catalog."C" DEFAULT None;
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50) COLLATE pg_catalog."C";
COMMENT ON COLUMN testschema."table_1_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_1_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_1_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL DEFAULT 1;
ADD COLUMN "col_1_$%{}[]()&*^!@""'`\/#" bigint NOT NULL DEFAULT 1;
COMMENT ON COLUMN testschema."table_1_$%{}[]()&*^!@""'`\/#"."col_1_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -22,15 +22,15 @@
"data": {
"name": "col_1_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for create",
"cltype":"bigint",
"attacl":[],
"is_primary_key":false,
"attnotnull":true,
"attlen":null,
"attprecision":null,
"attoptions":[],
"seclabels":[],
"defval":"1"
"cltype": "bigint",
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"defval": "1"
},
"expected_sql_file": "create_column_int.sql",
"expected_msql_file": "create_column_int.msql"
@@ -45,8 +45,37 @@
"attnum": 1,
"name": "new_col_1_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for alter",
"cltype":"real",
"attacl":{"added":[{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false},{"privilege_type":"w","privilege":true,"with_grant":false},{"privilege_type":"x","privilege":true,"with_grant":false}]}]}
"cltype": "real",
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "w",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_int.sql",
"expected_msql_file": "alter_column_int.msql"
@@ -60,7 +89,26 @@
"data": {
"attnum": 1,
"name": "new_col_1_$%{}[]()&*^!@\"'`\\/#",
"attacl":{"changed":[{"grantee":"postgres", "grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false}]}]}
"attacl": {
"changed": [
{
"grantee": "postgres",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_alt_privilege.sql",
"expected_msql_file": "alter_column_alt_privilege.msql"
@@ -83,16 +131,15 @@
"data": {
"name": "col_2_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for create",
"cltype":"character varying",
"cltype": "character varying",
"collspcname": "pg_catalog.\"C\"",
"attacl":[],
"is_primary_key":false,
"attnotnull":false,
"attlen":"50",
"attprecision":null,
"attoptions":[],
"seclabels":[],
"defval":null
"attacl": [],
"is_primary_key": false,
"attnotnull": false,
"attlen": "50",
"attprecision": "",
"attoptions": [],
"seclabels": []
},
"expected_sql_file": "create_column_char.sql",
"expected_msql_file": "create_column_char.msql"
@@ -110,8 +157,32 @@
"attstattarget": "5",
"attstorage": "p",
"description": "Comment for alter",
"cltype":"character",
"attacl":{"added":[{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false},{"privilege_type":"x","privilege":true,"with_grant":false}]}]}
"cltype": "character",
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_char.sql",
"expected_msql_file": "alter_column_char.msql"
@@ -125,7 +196,6 @@
"name": "new_col_2_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "create",
"name": "Create Column (Numeric type with Length Precision & Variables)",
@@ -135,17 +205,22 @@
"data": {
"name": "col_3_$%{}[]()&*^!@\"'`\\/#",
"description": "Comment for create",
"min_val":0,
"max_val":1000,
"cltype":"numeric",
"attacl":[],
"is_primary_key":false,
"attnotnull":true,
"attlen":"10",
"attprecision":"5",
"attidentity":"a",
"attoptions":[{"name":"n_distinct","value":"1"}],
"seclabels":[]
"min_val": 0,
"max_val": 1000,
"cltype": "numeric",
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": "10",
"attprecision": "5",
"attidentity": "a",
"attoptions": [
{
"name": "n_distinct",
"value": "1"
}
],
"seclabels": []
},
"expected_sql_file": "create_column_numeric.sql",
"expected_msql_file": "create_column_numeric.msql"
@@ -159,10 +234,39 @@
"data": {
"name": "new_col_3_$%{}[]()&*^!@\"'`\\/#",
"attnum": 3,
"attlen":"15",
"attprecision":"6",
"attlen": "15",
"attprecision": "6",
"description": "Comment for alter",
"attacl":{"added":[{"grantee":"PUBLIC","grantor":"postgres","privileges":[{"privilege_type":"a","privilege":true,"with_grant":false},{"privilege_type":"r","privilege":true,"with_grant":false},{"privilege_type":"w","privilege":true,"with_grant":false},{"privilege_type":"x","privilege":true,"with_grant":false}]}]}
"attacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "w",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_column_numeric.sql",
"expected_msql_file": "alter_column_numeric.msql"
@@ -175,7 +279,7 @@
"msql_endpoint": "NODE-column.msql_id",
"data": {
"attnum": 3,
"attlen":""
"attlen": ""
},
"expected_sql_file": "alter_column_remove_length.sql",
"expected_msql_file": "alter_column_remove_length.msql"
@@ -0,0 +1,13 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
RENAME "col__1_$%{}[]()&*^!@""'`\/#" TO "col__1_$%{}[]&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__1_$%{}[]&*^!@""'`\/#" SET DEFAULT 'changed default value'::text;
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__1_$%{}[]&*^!@""'`\/#" DROP NOT NULL;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]&*^!@""'`\/#"
IS 'test comment modify';
GRANT SELECT("col__1_$%{}[]&*^!@""'`\/#") ON testschema."table_2_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
@@ -0,0 +1,11 @@
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]&*^!@""'`\/#"
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__1_$%{}[]&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__1_$%{}[]&*^!@""'`\/#" text COLLATE pg_catalog."C" DEFAULT 'changed default value'::text;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]&*^!@""'`\/#"
IS 'test comment modify';
GRANT SELECT("col__1_$%{}[]&*^!@""'`\/#") ON testschema."table_2_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50, None) COLLATE pg_catalog."C" DEFAULT None;
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50) COLLATE pg_catalog."C";
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_6_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL GENERATED BY DEFAULT AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 10 CACHE 1 );
ADD COLUMN "col_6_$%{}[]()&*^!@""'`\/#" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 10 CACHE 1 );
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_6_$%{}[]()&*^!@""'`\/#"
IS 'demo comments';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_1_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL DEFAULT 1;
ADD COLUMN "col_1_$%{}[]()&*^!@""'`\/#" bigint NOT NULL DEFAULT 1;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_1_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_3_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL GENERATED ALWAYS AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
ADD COLUMN "col_3_$%{}[]()&*^!@""'`\/#" bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_3_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_5_$%{}[]()&*^!@""'`\/#" bigint(None, None) NOT NULL GENERATED BY DEFAULT AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
ADD COLUMN "col_5_$%{}[]()&*^!@""'`\/#" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( CYCLE INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 99999 CACHE 10 );
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_5_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
@@ -26,8 +26,8 @@
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": null,
"attprecision": null,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"defval": "1"
@@ -138,10 +138,9 @@
"is_primary_key": false,
"attnotnull": false,
"attlen": "50",
"attprecision": null,
"attprecision": "",
"attoptions": [],
"seclabels": [],
"defval": null
"seclabels": []
},
"expected_sql_file": "create_column_char.sql",
"expected_msql_file": "create_column_char.msql"
@@ -211,8 +210,8 @@
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": null,
"attprecision": null,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"attidentity": "a",
@@ -398,8 +397,8 @@
"attacl": [],
"is_primary_key": false,
"attnotnull": true,
"attlen": null,
"attprecision": null,
"attlen": "",
"attprecision": "",
"attoptions": [],
"seclabels": [],
"attidentity": "d",
@@ -468,8 +467,8 @@
"description": "demo comments",
"is_primary_key": false,
"attnotnull": true,
"attlen": null,
"attprecision": null,
"attlen": "",
"attprecision": "",
"attidentity": "d",
"seqincrement": "1",
"seqstart": "1",
Loaded 100 of 696 files, more files were not shown because too many files have changed in this diff. Show more