From 7bd0d55c8303bb276e695e4ed6c5ae26edfa4c82 Mon Sep 17 00:00:00 2001 From: Aditya Toshniwal Date: Fri, 12 Aug 2022 17:14:15 +0530 Subject: [PATCH] Fixed Security Hotspot reported by SonarQube. --- .../dashboard/static/js/WelcomeDashboard.jsx | 6 +- .../pg_utilities_maintenance_test.py | 2 +- web/pgadmin/misc/cloud/utils/__init__.py | 8 +- .../misc/static/explain/css/explain.css | 23 - .../misc/static/explain/img/ex_aggregate.svg | 1 - .../misc/static/explain/img/ex_append.svg | 1 - .../misc/static/explain/img/ex_bmp_and.svg | 1 - .../misc/static/explain/img/ex_bmp_heap.svg | 1 - .../misc/static/explain/img/ex_bmp_index.svg | 1 - .../misc/static/explain/img/ex_bmp_or.svg | 1 - .../explain/img/ex_broadcast_motion.svg | 1 - .../misc/static/explain/img/ex_cte_scan.svg | 1 - .../misc/static/explain/img/ex_delete.svg | 1 - .../static/explain/img/ex_foreign_scan.svg | 1 - .../static/explain/img/ex_gather_merge.svg | 1 - .../static/explain/img/ex_gather_motion.svg | 1 - .../misc/static/explain/img/ex_group.svg | 1 - .../misc/static/explain/img/ex_hash.svg | 1 - .../static/explain/img/ex_hash_anti_join.svg | 1 - .../static/explain/img/ex_hash_semi_join.svg | 1 - .../explain/img/ex_hash_setop_except.svg | 1 - .../explain/img/ex_hash_setop_except_all.svg | 1 - .../explain/img/ex_hash_setop_intersect.svg | 1 - .../img/ex_hash_setop_intersect_all.svg | 1 - .../explain/img/ex_hash_setop_unknown.svg | 1 - .../static/explain/img/ex_index_only_scan.svg | 1 - .../misc/static/explain/img/ex_index_scan.svg | 1 - .../misc/static/explain/img/ex_insert.svg | 1 - .../misc/static/explain/img/ex_join.svg | 1 - .../misc/static/explain/img/ex_limit.svg | 1 - .../misc/static/explain/img/ex_lock_rows.svg | 1 - .../static/explain/img/ex_materialize.svg | 1 - .../misc/static/explain/img/ex_merge.svg | 1 - .../static/explain/img/ex_merge_anti_join.svg | 1 - .../static/explain/img/ex_merge_append.svg | 1 - .../static/explain/img/ex_merge_semi_join.svg | 1 - .../explain/img/ex_named_tuplestore_scan.svg | 1 - .../misc/static/explain/img/ex_nested.svg | 1 - .../explain/img/ex_nested_loop_anti_join.svg | 1 - .../explain/img/ex_nested_loop_semi_join.svg | 1 - .../misc/static/explain/img/ex_projectset.svg | 1 - .../static/explain/img/ex_recursive_union.svg | 1 - .../explain/img/ex_redistribute_motion.svg | 1 - .../misc/static/explain/img/ex_result.svg | 1 - .../misc/static/explain/img/ex_scan.svg | 1 - .../misc/static/explain/img/ex_seek.svg | 1 - .../misc/static/explain/img/ex_setop.svg | 1 - .../misc/static/explain/img/ex_sort.svg | 1 - .../misc/static/explain/img/ex_subplan.svg | 1 - .../static/explain/img/ex_table_func_scan.svg | 1 - .../misc/static/explain/img/ex_tid_scan.svg | 1 - .../misc/static/explain/img/ex_unique.svg | 1 - .../misc/static/explain/img/ex_unknown.svg | 1 - .../misc/static/explain/img/ex_update.svg | 1 - .../static/explain/img/ex_values_scan.svg | 1 - .../explain/img/ex_window_aggregate.svg | 1 - .../static/explain/img/ex_worktable_scan.svg | 1 - web/pgadmin/misc/static/explain/js/explain.js | 1607 ----------------- .../static/explain/js/explain_statistics.js | 127 -- .../misc/static/explain/js/image_mapper.js | 300 --- .../misc/static/explain/js/svg_downloader.js | 30 - .../misc/static/explain/scss/_explain.scss | 146 -- .../javascript/browser/generate_url_spec.js | 12 +- .../misc/explain/explain_statistics_spec.js | 106 -- web/webpack.shim.js | 1 - 65 files changed, 14 insertions(+), 2407 deletions(-) delete mode 100644 web/pgadmin/misc/static/explain/css/explain.css delete mode 100644 web/pgadmin/misc/static/explain/img/ex_aggregate.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_append.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_bmp_and.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_bmp_heap.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_bmp_index.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_bmp_or.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_broadcast_motion.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_cte_scan.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_delete.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_foreign_scan.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_gather_merge.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_gather_motion.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_group.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_hash.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_hash_anti_join.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_hash_semi_join.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_hash_setop_except.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_hash_setop_except_all.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_hash_setop_intersect.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_hash_setop_intersect_all.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_hash_setop_unknown.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_index_only_scan.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_index_scan.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_insert.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_join.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_limit.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_lock_rows.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_materialize.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_merge.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_merge_anti_join.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_merge_append.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_merge_semi_join.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_named_tuplestore_scan.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_nested.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_nested_loop_anti_join.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_nested_loop_semi_join.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_projectset.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_recursive_union.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_redistribute_motion.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_result.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_scan.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_seek.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_setop.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_sort.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_subplan.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_table_func_scan.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_tid_scan.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_unique.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_unknown.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_update.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_values_scan.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_window_aggregate.svg delete mode 100644 web/pgadmin/misc/static/explain/img/ex_worktable_scan.svg delete mode 100644 web/pgadmin/misc/static/explain/js/explain.js delete mode 100644 web/pgadmin/misc/static/explain/js/explain_statistics.js delete mode 100644 web/pgadmin/misc/static/explain/js/image_mapper.js delete mode 100644 web/pgadmin/misc/static/explain/js/svg_downloader.js delete mode 100644 web/pgadmin/misc/static/explain/scss/_explain.scss delete mode 100644 web/regression/javascript/misc/explain/explain_statistics_spec.js diff --git a/web/pgadmin/dashboard/static/js/WelcomeDashboard.jsx b/web/pgadmin/dashboard/static/js/WelcomeDashboard.jsx index 653754055..386973874 100644 --- a/web/pgadmin/dashboard/static/js/WelcomeDashboard.jsx +++ b/web/pgadmin/dashboard/static/js/WelcomeDashboard.jsx @@ -181,7 +181,7 @@ export default function WelcomeDashboard({ pgBrowser }) {
@@ -205,7 +205,7 @@ export default function WelcomeDashboard({ pgBrowser }) {
@@ -219,7 +219,7 @@ export default function WelcomeDashboard({ pgBrowser }) {
diff --git a/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py b/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py index 0724632cc..22158907c 100644 --- a/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py +++ b/web/pgadmin/feature_tests/pg_utilities_maintenance_test.py @@ -85,7 +85,7 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest): By.XPATH, NavMenuLocators.maintenance_operation), 10) # Wait for the backup started alert - test_gui_helper.wait_for_process_start() + test_gui_helper.wait_for_process_start(self) self.verify_command() def _open_maintenance_dialogue(self): diff --git a/web/pgadmin/misc/cloud/utils/__init__.py b/web/pgadmin/misc/cloud/utils/__init__.py index ecf39c996..41ae9d1eb 100644 --- a/web/pgadmin/misc/cloud/utils/__init__.py +++ b/web/pgadmin/misc/cloud/utils/__init__.py @@ -11,7 +11,6 @@ import urllib3 import ipaddress from flask_security import current_user from pgadmin.misc.bgprocess.processes import IProcessDesc -from pgadmin.utils import html from pgadmin.model import db, Server from flask_babel import gettext from pgadmin.utils import get_server @@ -19,12 +18,13 @@ from pgadmin.utils import get_server def get_my_ip(): """ Return the public IP of this host """ - http = urllib3.PoolManager() + urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + http = urllib3.PoolManager(cert_reqs='CERT_NONE') try: - external_ip = http.request('GET', 'http://ifconfig.me/ip').data + external_ip = http.request('GET', 'https://ifconfig.me/ip').data except Exception: try: - external_ip = http.request('GET', 'http://ident.me').data + external_ip = http.request('GET', 'https://ident.me').data except Exception: external_ip = '127.0.0.1' diff --git a/web/pgadmin/misc/static/explain/css/explain.css b/web/pgadmin/misc/static/explain/css/explain.css deleted file mode 100644 index d1f8bbb27..000000000 --- a/web/pgadmin/misc/static/explain/css/explain.css +++ /dev/null @@ -1,23 +0,0 @@ -.explain-tooltip { - display: table-cell; - text-align: left; - white-space: nowrap; - padding: 2px !important; - font-size: small; -} - -td.explain-tooltip-val { - display: table-cell; - text-align: left; - white-space: pre-wrap; - padding: 2px !important; - font-size: small; - font-weight: normal; -} - -.pgadmin-tooltip-table { - border-collapse: collapse; - border-spacing: 1px; - top: auto; - left: auto; -} diff --git a/web/pgadmin/misc/static/explain/img/ex_aggregate.svg b/web/pgadmin/misc/static/explain/img/ex_aggregate.svg deleted file mode 100644 index f6342e50d..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_aggregate.svg +++ /dev/null @@ -1 +0,0 @@ -ex_aggregate \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_append.svg b/web/pgadmin/misc/static/explain/img/ex_append.svg deleted file mode 100644 index c43597c84..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_append.svg +++ /dev/null @@ -1 +0,0 @@ -ex_append \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_bmp_and.svg b/web/pgadmin/misc/static/explain/img/ex_bmp_and.svg deleted file mode 100644 index 4393178eb..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_bmp_and.svg +++ /dev/null @@ -1 +0,0 @@ -ex_bmp_and1010000111 \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_bmp_heap.svg b/web/pgadmin/misc/static/explain/img/ex_bmp_heap.svg deleted file mode 100644 index 8eed51610..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_bmp_heap.svg +++ /dev/null @@ -1 +0,0 @@ -ex_bmp_heap10100 \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_bmp_index.svg b/web/pgadmin/misc/static/explain/img/ex_bmp_index.svg deleted file mode 100644 index 8e78f5c0a..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_bmp_index.svg +++ /dev/null @@ -1 +0,0 @@ -ex_bmp_index01100 \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_bmp_or.svg b/web/pgadmin/misc/static/explain/img/ex_bmp_or.svg deleted file mode 100644 index 47bb86296..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_bmp_or.svg +++ /dev/null @@ -1 +0,0 @@ -ex_bmp_or1010000111 \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_broadcast_motion.svg b/web/pgadmin/misc/static/explain/img/ex_broadcast_motion.svg deleted file mode 100644 index b34ba1a8a..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_broadcast_motion.svg +++ /dev/null @@ -1 +0,0 @@ -ex_broadcast_motion \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_cte_scan.svg b/web/pgadmin/misc/static/explain/img/ex_cte_scan.svg deleted file mode 100644 index ac1861067..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_cte_scan.svg +++ /dev/null @@ -1 +0,0 @@ -ex_cte_scanCTE \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_delete.svg b/web/pgadmin/misc/static/explain/img/ex_delete.svg deleted file mode 100644 index 89d96805b..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_delete.svg +++ /dev/null @@ -1 +0,0 @@ -ex_delete \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_foreign_scan.svg b/web/pgadmin/misc/static/explain/img/ex_foreign_scan.svg deleted file mode 100644 index a9f1c3d2b..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_foreign_scan.svg +++ /dev/null @@ -1 +0,0 @@ -ex_foreign_scanCTE \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_gather_merge.svg b/web/pgadmin/misc/static/explain/img/ex_gather_merge.svg deleted file mode 100644 index 4c6f1dc7e..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_gather_merge.svg +++ /dev/null @@ -1 +0,0 @@ -gather_merge \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_gather_motion.svg b/web/pgadmin/misc/static/explain/img/ex_gather_motion.svg deleted file mode 100644 index b3f2081ad..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_gather_motion.svg +++ /dev/null @@ -1 +0,0 @@ -ex_gather_motion \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_group.svg b/web/pgadmin/misc/static/explain/img/ex_group.svg deleted file mode 100644 index 44aa97fe2..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_group.svg +++ /dev/null @@ -1 +0,0 @@ -ex_group \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_hash.svg b/web/pgadmin/misc/static/explain/img/ex_hash.svg deleted file mode 100644 index dfd8c6cb7..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_hash.svg +++ /dev/null @@ -1 +0,0 @@ -ex_hash \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_hash_anti_join.svg b/web/pgadmin/misc/static/explain/img/ex_hash_anti_join.svg deleted file mode 100644 index 39a9354b8..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_hash_anti_join.svg +++ /dev/null @@ -1 +0,0 @@ -ex_hash_anti_join \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_hash_semi_join.svg b/web/pgadmin/misc/static/explain/img/ex_hash_semi_join.svg deleted file mode 100644 index c0d9886d6..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_hash_semi_join.svg +++ /dev/null @@ -1 +0,0 @@ -ex_hash_semi_join \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_hash_setop_except.svg b/web/pgadmin/misc/static/explain/img/ex_hash_setop_except.svg deleted file mode 100644 index 6d8319931..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_hash_setop_except.svg +++ /dev/null @@ -1 +0,0 @@ -ex_hash_setop_except \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_hash_setop_except_all.svg b/web/pgadmin/misc/static/explain/img/ex_hash_setop_except_all.svg deleted file mode 100644 index c47b1081d..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_hash_setop_except_all.svg +++ /dev/null @@ -1 +0,0 @@ -ex_hash_setop_except_allAll \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_hash_setop_intersect.svg b/web/pgadmin/misc/static/explain/img/ex_hash_setop_intersect.svg deleted file mode 100644 index b3c4ab7af..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_hash_setop_intersect.svg +++ /dev/null @@ -1 +0,0 @@ -ex_hash_setop_intersect \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_hash_setop_intersect_all.svg b/web/pgadmin/misc/static/explain/img/ex_hash_setop_intersect_all.svg deleted file mode 100644 index 0ba7e4469..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_hash_setop_intersect_all.svg +++ /dev/null @@ -1 +0,0 @@ -ex_hash_setop_intersect_allAll \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_hash_setop_unknown.svg b/web/pgadmin/misc/static/explain/img/ex_hash_setop_unknown.svg deleted file mode 100644 index bfaadcff3..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_hash_setop_unknown.svg +++ /dev/null @@ -1 +0,0 @@ -ex_hash_setop_unknown? \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_index_only_scan.svg b/web/pgadmin/misc/static/explain/img/ex_index_only_scan.svg deleted file mode 100644 index e27c79924..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_index_only_scan.svg +++ /dev/null @@ -1 +0,0 @@ -ex_index_only_scan \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_index_scan.svg b/web/pgadmin/misc/static/explain/img/ex_index_scan.svg deleted file mode 100644 index 0b5b1b03d..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_index_scan.svg +++ /dev/null @@ -1 +0,0 @@ -ex_index_scan \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_insert.svg b/web/pgadmin/misc/static/explain/img/ex_insert.svg deleted file mode 100644 index 202beaa4e..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_insert.svg +++ /dev/null @@ -1 +0,0 @@ -ex_insert \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_join.svg b/web/pgadmin/misc/static/explain/img/ex_join.svg deleted file mode 100644 index 30146a9ea..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_join.svg +++ /dev/null @@ -1 +0,0 @@ -ex_join \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_limit.svg b/web/pgadmin/misc/static/explain/img/ex_limit.svg deleted file mode 100644 index 244317a72..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_limit.svg +++ /dev/null @@ -1 +0,0 @@ -ex_limit \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_lock_rows.svg b/web/pgadmin/misc/static/explain/img/ex_lock_rows.svg deleted file mode 100644 index 001ab5f85..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_lock_rows.svg +++ /dev/null @@ -1 +0,0 @@ -ex_lock_rows \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_materialize.svg b/web/pgadmin/misc/static/explain/img/ex_materialize.svg deleted file mode 100644 index b0b87457a..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_materialize.svg +++ /dev/null @@ -1 +0,0 @@ -ex_materialize \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_merge.svg b/web/pgadmin/misc/static/explain/img/ex_merge.svg deleted file mode 100644 index 5f448693b..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_merge.svg +++ /dev/null @@ -1 +0,0 @@ -ex_merge \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_merge_anti_join.svg b/web/pgadmin/misc/static/explain/img/ex_merge_anti_join.svg deleted file mode 100644 index 2e7a00d65..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_merge_anti_join.svg +++ /dev/null @@ -1 +0,0 @@ -ex_merge_anti_join \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_merge_append.svg b/web/pgadmin/misc/static/explain/img/ex_merge_append.svg deleted file mode 100644 index 540f8a969..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_merge_append.svg +++ /dev/null @@ -1 +0,0 @@ -ex_merge_append \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_merge_semi_join.svg b/web/pgadmin/misc/static/explain/img/ex_merge_semi_join.svg deleted file mode 100644 index 672cd4e5a..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_merge_semi_join.svg +++ /dev/null @@ -1 +0,0 @@ -ex_merge_semi_join \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_named_tuplestore_scan.svg b/web/pgadmin/misc/static/explain/img/ex_named_tuplestore_scan.svg deleted file mode 100644 index 3d0fa55ff..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_named_tuplestore_scan.svg +++ /dev/null @@ -1 +0,0 @@ -named_tuplestore_scan \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_nested.svg b/web/pgadmin/misc/static/explain/img/ex_nested.svg deleted file mode 100644 index 3623675b2..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_nested.svg +++ /dev/null @@ -1 +0,0 @@ -ex_nested \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_nested_loop_anti_join.svg b/web/pgadmin/misc/static/explain/img/ex_nested_loop_anti_join.svg deleted file mode 100644 index 085cf6b18..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_nested_loop_anti_join.svg +++ /dev/null @@ -1 +0,0 @@ -ex_nested_loop_anti_join \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_nested_loop_semi_join.svg b/web/pgadmin/misc/static/explain/img/ex_nested_loop_semi_join.svg deleted file mode 100644 index b39cb6936..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_nested_loop_semi_join.svg +++ /dev/null @@ -1 +0,0 @@ -ex_nested_loop_semi_join \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_projectset.svg b/web/pgadmin/misc/static/explain/img/ex_projectset.svg deleted file mode 100644 index 5943ed4aa..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_projectset.svg +++ /dev/null @@ -1 +0,0 @@ -projectset \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_recursive_union.svg b/web/pgadmin/misc/static/explain/img/ex_recursive_union.svg deleted file mode 100644 index fb5e2e402..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_recursive_union.svg +++ /dev/null @@ -1 +0,0 @@ -ex_recursive_union \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_redistribute_motion.svg b/web/pgadmin/misc/static/explain/img/ex_redistribute_motion.svg deleted file mode 100644 index dd7d95353..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_redistribute_motion.svg +++ /dev/null @@ -1 +0,0 @@ -ex_redistribute_motion \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_result.svg b/web/pgadmin/misc/static/explain/img/ex_result.svg deleted file mode 100644 index f8bbd0ab6..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_result.svg +++ /dev/null @@ -1 +0,0 @@ -ex_result \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_scan.svg b/web/pgadmin/misc/static/explain/img/ex_scan.svg deleted file mode 100644 index fe3216105..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_scan.svg +++ /dev/null @@ -1 +0,0 @@ -ex_scan \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_seek.svg b/web/pgadmin/misc/static/explain/img/ex_seek.svg deleted file mode 100644 index 6a75a5eab..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_seek.svg +++ /dev/null @@ -1 +0,0 @@ -ex_seek \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_setop.svg b/web/pgadmin/misc/static/explain/img/ex_setop.svg deleted file mode 100644 index 43b309b5f..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_setop.svg +++ /dev/null @@ -1 +0,0 @@ -ex_setop \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_sort.svg b/web/pgadmin/misc/static/explain/img/ex_sort.svg deleted file mode 100644 index 568639aad..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_sort.svg +++ /dev/null @@ -1 +0,0 @@ -ex_sort \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_subplan.svg b/web/pgadmin/misc/static/explain/img/ex_subplan.svg deleted file mode 100644 index e98e99f73..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_subplan.svg +++ /dev/null @@ -1 +0,0 @@ -ex_subplan \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_table_func_scan.svg b/web/pgadmin/misc/static/explain/img/ex_table_func_scan.svg deleted file mode 100644 index 7a8555506..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_table_func_scan.svg +++ /dev/null @@ -1 +0,0 @@ -table_fun_scan \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_tid_scan.svg b/web/pgadmin/misc/static/explain/img/ex_tid_scan.svg deleted file mode 100644 index d42bafd57..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_tid_scan.svg +++ /dev/null @@ -1 +0,0 @@ -ex_tid_scan \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_unique.svg b/web/pgadmin/misc/static/explain/img/ex_unique.svg deleted file mode 100644 index d6cc261b4..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_unique.svg +++ /dev/null @@ -1 +0,0 @@ -ex_unique \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_unknown.svg b/web/pgadmin/misc/static/explain/img/ex_unknown.svg deleted file mode 100644 index 3af69574d..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_unknown.svg +++ /dev/null @@ -1 +0,0 @@ -ex_unknown \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_update.svg b/web/pgadmin/misc/static/explain/img/ex_update.svg deleted file mode 100644 index 1f82bb1db..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_update.svg +++ /dev/null @@ -1 +0,0 @@ -ex_update \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_values_scan.svg b/web/pgadmin/misc/static/explain/img/ex_values_scan.svg deleted file mode 100644 index 42c831901..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_values_scan.svg +++ /dev/null @@ -1 +0,0 @@ -ex_values_scan \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_window_aggregate.svg b/web/pgadmin/misc/static/explain/img/ex_window_aggregate.svg deleted file mode 100644 index 85b3c855c..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_window_aggregate.svg +++ /dev/null @@ -1 +0,0 @@ -ex_window_aggregate \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/img/ex_worktable_scan.svg b/web/pgadmin/misc/static/explain/img/ex_worktable_scan.svg deleted file mode 100644 index eebc0169c..000000000 --- a/web/pgadmin/misc/static/explain/img/ex_worktable_scan.svg +++ /dev/null @@ -1 +0,0 @@ -ex_worktable_scanWORKTABLE \ No newline at end of file diff --git a/web/pgadmin/misc/static/explain/js/explain.js b/web/pgadmin/misc/static/explain/js/explain.js deleted file mode 100644 index 985f0a7d7..000000000 --- a/web/pgadmin/misc/static/explain/js/explain.js +++ /dev/null @@ -1,1607 +0,0 @@ -///////////////////////////////////////////////////////////// -// -// pgAdmin 4 - PostgreSQL Tools -// -// Copyright (C) 2013 - 2022, The pgAdmin Development Team -// This software is released under the PostgreSQL Licence -// -////////////////////////////////////////////////////////////// - -define('pgadmin.misc.explain', [ - 'sources/url_for', 'jquery', 'underscore', - 'sources/pgadmin', 'backbone', 'explain_statistics', - 'svg_downloader', 'image_mapper', 'sources/gettext', 'bootstrap', -], function( - url_for, $, _, pgAdmin, Backbone, StatisticsModel, - svgDownloader, imageMapper, gettext -) { - - pgAdmin = pgAdmin || window.pgAdmin || {}; - svgDownloader = svgDownloader.default; - var Snap = null; - - var initSnap = function(snapModule) { - Snap = snapModule; - // Snap.svg plug-in to write multitext as image name - Snap.plugin(function(_Snap, Element, Paper) { - Paper.prototype.multitext = function(x, y, txt, max_width, attributes) { - var svg = _Snap(), - abc = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', - temp = svg.text(0, 0, abc); - - temp.attr(attributes); - - /* - * Find letter width in pixels and - * index from where the text should be broken - */ - var letter_width = temp.getBBox().width / abc.length, - word_break_index = Math.round((max_width / letter_width)) - 1; - - svg.remove(); - - var words = txt.split(' '), - width_so_far = 0, - lines = [], - curr_line = '', - /* - * Function to divide string into multiple lines - * and store them in an array if it size crosses - * the max-width boundary. - */ - splitTextInMultiLine = function(leading, so_far, line) { - var l = line.length, - res = []; - - if (l == 0) - return res; - - if (so_far && (so_far + (l * letter_width) > max_width)) { - res.push(leading); - res = res.concat(splitTextInMultiLine('', 0, line)); - } else if (so_far) { - res.push(leading + ' ' + line); - } else { - if (leading) - res.push(leading); - if (line.length > word_break_index + 1) - res.push(line.slice(0, word_break_index) + '-'); - else - res.push(line); - res = res.concat(splitTextInMultiLine('', 0, line.slice(word_break_index))); - } - - return res; - }; - - for (let word_val of words) { - var tmpArr = splitTextInMultiLine( - curr_line, width_so_far, word_val - ); - - if (curr_line) { - lines = lines.slice(0, lines.length - 1); - } - lines = lines.concat(tmpArr); - curr_line = lines[lines.length - 1]; - width_so_far = (curr_line.length * letter_width); - } - - // Create multiple tspan for each string in array - var t = this.text(x, y, lines).attr(attributes); - t.selectAll('tspan:nth-child(n+2)').attr({ - dy: '1.2em', - x: x, - }); - return t; - }; - }); - }; - - if (pgAdmin.Explain) - return pgAdmin.Explain; - - var pgExplain = pgAdmin.Explain = { - // Prefix path where images are stored - prefix: url_for('misc.index') + 'static/explain/img/', - }; - - // Some predefined constants used to calculate image location and its border - var pWIDTH = 100.; - var pHEIGHT = 100.; - var IMAGE_WIDTH = 50; - var IMAGE_HEIGHT = 50; - var offsetX = 200, - offsetY = 60; - var ARROW_WIDTH = 10, - ARROW_HEIGHT = 10, - DEFAULT_ARROW_SIZE = 2; - var TXT_ALIGN = 5, - TXT_SIZE = '15px'; - var xMargin = 25, - yMargin = 25; - var MIN_ZOOM_FACTOR = 0.01, - MAX_ZOOM_FACTOR = 2, - INIT_ZOOM_FACTOR = 1; - var ZOOM_RATIO = 0.05; - - var _createExplainTable = () => { - return $([ - '', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - /* - * TODO:: Remove the 'd-none' class, when showing the extra info row - * implemented. - */ - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - '
', - '', - '
', - ].join('')); - }; - - var _renderExplainTable = (_data, $_container) => { - var $explainTableData = $(''); - _.each(_data.rows, (_row) => { - var $tblRow = $(_row); - $tblRow.appendTo($explainTableData); - }); - $explainTableData.appendTo($_container); - - if (_data.show_timings === true) { - $_container.find('.timings').removeClass('d-none'); - } - - if (_data.show_rowsx === true) { - $_container.find('.rowsx').removeClass('d-none'); - } else if (_data.show_rows === true) { - $_container.find('.rows').removeClass('d-none'); - $_container.find('thead .rows[colspan=3]').attr('colspan', 1); - } else if (_data.show_plan_rows === true) { - $_container.find('.plan_rows').removeClass('d-none'); - $_container.find('thead .rows[colspan=3]').attr('colspan', 1); - } - }; - - var _createStatisticsTables = () => { - return $([ - '
', - '
', - '
', - gettext('Statistics per Node Type'), - '
', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - '
', - '
', - '
', - '
', - gettext('Statistics per Relation'), - '
', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - ' ', - '
', - '
', - '
', - ].join('')); - }; - - var _statisticRowTemplate = _.template([ - ' class="<%=className%>"<%}%>>', - ' <%- data.name %>', - ' <%- data.count %>', - ' ', - '<%=Math.ceil10(data.sum_of_times, -3)%> ms', - '', - ' ', - '<%=Math.ceil10(((data.sum_of_times||0)/(total_time||1)) * 100, -2)%>%', - '', - '', - ].join('')); - - var _renderStatisticsTable = (_data, $_container) => { - var $perTableTbl = $_container.find('table[for="per_table"]'), - $perNodeTbl = $_container.find('table[for="per_node_type"]'); - - _.each( - _.sortBy(_.values(_data.statistics.nodes), 'name'), - (_node) => ( - $perNodeTbl.append(_statisticRowTemplate({ - 'data': _node, 'total_time': _data.total_time, - 'className': '', - })) - ) - ); - - _.each( - _.sortBy(_.values(_data.statistics.tables), 'name'), - (_table) => { - _table.sum_of_times = 0; - _.each(_table.nodes, (_node) => ( - _table.sum_of_times += _node.sum_of_times - )); - $perTableTbl.append(_statisticRowTemplate({ - 'data': _table, 'total_time': _data.total_time, - 'className': 'table', - })); - - _.each( - _.sortBy(_.values(_table.nodes), 'name'), - (_node) => { - $perTableTbl.append(_statisticRowTemplate({ - 'data': _node, 'total_time': _table.sum_of_times, - 'className': 'node', - })); - } - ); - } - ); - - if (_data.show_timings) { - $_container.find('.timings').removeClass('d-none'); - } - }; - - var _explainRowTemplate = _.template([ - ' 0) {%>', - ' pga-ex-collapsible', - '<%}%>', - '<% if (data["exclusive_flag"] !== "undefined") {%>', - ' pga-ex-exclusive-', '<%- data["exclusive_flag"] %>', - '<%}%>', - '<% if (data["inclusive_flag"] !== "undefined") {%>', - ' pga-ex-inclusive-', '<%- data["inclusive_flag"] %>', - '<%}%>', - '<% if (data["rowsx_flag"] !== "undefined") {%>', - ' pga-ex-rowsx-', '<%- data["rowsx_flag"] %>', - '<%}%>', - '"', - '<% if (data["parent_node"]) {%>', - ' data-parent="pga_ex_<%= data["parent_node"] %>"', - '<%}%>', - ' data-ex-id="pga_ex_<%= data["level"].join("_") %>">', - ' ', - ' ', - '', - ' ', - '<%= (data["_serial"]) %>.', - ' px"', - 'title="<%= tooltip_text %>"', - '>', - ' ', - '<%= display_text %>', - '<%if (node_extra_info && node_extra_info.length > 0 ) {%>', - '', - '<% for (var node_info_idx=0; ', - ' node_info_idx', - '
  • ', '<%= node_extra_info[node_info_idx] %>', '
  • ', - '<% }%>', - '
    ', - '<%}%>', - ' ', - ' ', - 'pga-ex-exclusive-', '<%- data["exclusive_flag"] %>', - '<%}%>', - '">', - '<% if (typeof(data["exclusive"]) !== "undefined") {%>', '<%= data["exclusive"] %> ms', '<%}%>', - ' ', - ' ', - 'pga-ex-inclusive-', '<%- data["inclusive_flag"] %>', - '<%}%>', - '">', - '<% if (typeof(data["inclusive"]) !== "undefined") {%>', '<%= data["inclusive"] %> ms', '<%}%>', - ' ', - ' ', - 'pga-ex-rowsx-', '<%- data["rowsx_flag"] %>', - '<%}%>', - '">', - '<% if (data["rowsx_direction"] === "positive") {%>', - '↑', - '<%} else {%>', - '↓', - '<%}%> ', - '<% if (typeof(data["rowsx"]) !== "undefined") {%>', - '<%- data["rowsx"] %>', - '<%}%> ', - ' ', - ' ', - '<% if (typeof(data["Actual Rows"]) !== "undefined") {%>', - '<%= data["Actual Rows"] %>', - '<%}%>', - ' ', - ' ', - '<%= data["Plan Rows"] %>', - ' ', - ' ', - '<% if (typeof(data["Actual Loops"]) !== "undefined") {%>', - '<%= data["Actual Loops"] %>', - '<%}%>', - ' ', - ' ', - ' ', - ' ', - '', - ].join('')); - - var _nodeExplainTableData = (_planData, _ctx) => { - let node_info, - display_text = [''], - tooltip = [], - node_extra_info = [], - info = _ctx._explainTable; - - // Display: [ using ] [ on .[ as ]] - - if (/Scan/.test(_planData['Node Type'])) { - display_text.push(_planData['Node Type']); - tooltip.push(_planData['Node Type']); - } else { - display_text.push(_planData['image_text']); - tooltip.push(_planData['image_text']); - } - node_info = tooltip.join(''); - display_text.push(''); - - if (typeof(_planData['Index Name']) !== 'undefined') { - display_text.push(' using '); - tooltip.push(' using '); - display_text.push(''); - display_text.push(_.escape(_planData['Index Name'])); - tooltip.push(_planData['Index Name']); - display_text.push(''); - } - - if (typeof(_planData['Relation Name']) !== 'undefined') { - display_text.push(' on '); - tooltip.push(' on '); - if (typeof(_planData['Schema']) !== 'undefined') { - display_text.push(''); - display_text.push(_.escape(_planData['Schema'])); - tooltip.push(_planData['Schema']); - display_text.push(''); - display_text.push('.'); - tooltip.push('.'); - } - display_text.push(''); - display_text.push(_.escape(_planData['Relation Name'])); - tooltip.push(_planData['Relation Name']); - display_text.push(''); - - if (typeof(_planData['Alias']) !== 'undefined') { - display_text.push(' as '); - tooltip.push(' as '); - display_text.push(''); - display_text.push(_.escape(_planData['Alias'])); - tooltip.push(_.escape(_planData['Alias'])); - display_text.push(''); - } - } - - if ( - typeof(_planData['Plan Rows']) !== 'undefined' && - typeof(_planData['Plan Width']) !== 'undefined' - ) { - let cost = [ - ' (cost=', - (typeof(_planData['Startup Cost']) !== 'undefined' ? - _planData['Startup Cost'] : ''), - '..', - (typeof(_planData['Total Cost']) !== 'undefined' ? - _planData['Total Cost'] : ''), - ' rows=', - _planData['Plan Rows'], - ' width=', - _planData['Plan Width'], - ')', - ].join(''); - display_text.push(cost); - tooltip.push(cost); - } - - if ( - typeof(_planData['Actual Startup Time']) !== 'undefined' || - typeof(_planData['Actual Total Time']) !== 'undefined' || - typeof(_planData['Actual Rows']) !== 'undefined' - ) { - let actual = [ - ' (', - (typeof(_planData['Actual Startup Time']) !== 'undefined' ? - ('actual=' + _planData['Actual Startup Time']) + '..' : '' - ), - (typeof(_planData['Actual Total Time']) !== 'undefined' ? - _planData['Actual Total Time'] + ' ' : '' - ), - (typeof(_planData['Actual Rows']) !== 'undefined' ? - ('rows=' + _planData['Actual Rows']) : '' - ), - (typeof(_planData['Actual Loops']) !== 'undefined' ? - (' loops=' + _planData['Actual Loops']) : '' - ), - ')', - ].join(''); - - display_text.push(actual); - tooltip.push(actual); - } - - if ('Join Filter' in _planData) { - node_extra_info.push( - '' + gettext('Join Filter') + ': ' + _.escape(_planData['Join Filter']) - ); - } - - if ('Filter' in _planData) { - node_extra_info.push('' + gettext('Filter') + ': ' + _.escape(_planData['Filter'])); - } - - if ('Index Cond' in _planData) { - node_extra_info.push('' + gettext('Index Cond') + ': ' + _.escape(_planData['Index Cond'])); - } - - if ('Hash Cond' in _planData) { - node_extra_info.push('' + gettext('Hash Cond') + ': ' + _.escape(_planData['Hash Cond'])); - } - - if ('Rows Removed by Filter' in _planData) { - node_extra_info.push( - '' + gettext('Rows Removed by Filter') + ': ' + - _.escape(_planData['Rows Removed by Filter']) - ); - } - - if ('Peak Memory Usage' in _planData) { - var buffer = [ - '' + gettext('Buckets') + ':', _.escape(_planData['Hash Buckets']), - '' + gettext('Batches') + ':', _.escape(_planData['Hash Batches']), - '' + gettext('Memory Usage') + ':', _.escape(_planData['Peak Memory Usage']), 'kB', - ].join(' '); - node_extra_info.push(buffer); - } - - if ('Recheck Cond' in _planData) { - node_extra_info.push('' + gettext('Recheck Cond') + ': ' + _planData['Recheck Cond']); - } - - if ('Exact Heap Blocks' in _planData) { - node_extra_info.push('' + gettext('Heap Blocks') + ': exact=' + _planData['Exact Heap Blocks']); - } - - info.rows.push(_explainRowTemplate({ - data: _planData, - display_text: display_text.join(''), - tooltip_text: tooltip.join(''), - node_extra_info: node_extra_info, - })); - - if (typeof(_planData['exclusive_flag']) !== 'undefined') { - info.show_timings = true; - } - - if (typeof(_planData['rowsx_flag']) !== 'undefined') { - info.show_rowsx = true; - } - - if (typeof(_planData['Actual Loops']) !== 'undefined') { - info.show_rows = true; - } - - if (typeof(_planData['Plan Rows']) !== 'undefined') { - info.show_plan_rows = true; - } - - if (typeof(_planData['total_time']) !== 'undefined') { - info.total_time = _planData['total_time']; - } - - let node; - - if (typeof(_planData['Relation Name']) !== 'undefined') { - let relationName = ( - typeof(_planData['Schema']) !== 'undefined' ? - (_planData['Schema'] + '.') : '' - ) + _planData['Relation Name'], - table = info.statistics.tables[relationName] || { - name: relationName, - count: 0, - sum_of_times: 0, - nodes: {}, - }; - - node = table.nodes[node_info] || { - name: node_info, - count: 0, - sum_of_times: 0, - }; - - table.count++; - table.sum_of_times += _planData['exclusive']; - node.count++; - node.sum_of_times += _planData['exclusive']; - - table.nodes[node_info] = node; - info.statistics.tables[relationName] = table; - } - - node = info.statistics.nodes[node_info] || { - name: node_info, - count: 0, - sum_of_times: 0, - }; - - node.count++; - node.sum_of_times += _planData['exclusive']; - info.statistics.nodes[node_info] = node; - }; - - // Backbone model for each plan property of input JSON object - var PlanModel = Backbone.Model.extend({ - defaults: { - 'Plans': [], - level: [], - 'image': undefined, - 'image_text': undefined, - xpos: undefined, - ypos: undefined, - width: pWIDTH, - height: pHEIGHT, - }, - - _createSame: function() { - return new PlanModel(); - }, - - parse: function(data, _opt) { - var idx = 1, - lvl = data.level = data.level || [idx], - plans = [], - node_type = data['Node Type'], - // Calculating relative xpos of current node from top node - xpos = data.xpos = data.xpos - pWIDTH, - // Calculating relative ypos of current node from top node - ypos = data.ypos, - maxChildWidth = 0; - - _opt.ctx.totalNodes++; - _opt.ctx._explainTable.total_time = data['total_time'] || data['Actual Total Time']; - - data['_serial'] = _opt.ctx.totalNodes; - data['width'] = pWIDTH; - data['height'] = pHEIGHT; - - /* - * calculating xpos, ypos, width and height if current node is a subplan - */ - if (data['Parent Relationship'] === 'SubPlan') { - data['width'] += (xMargin * 2) + (xMargin / 2); - data['height'] += (yMargin * 2); - data['ypos'] += yMargin; - xpos -= xMargin; - ypos += yMargin; - } - - if (node_type.startsWith('(slice')) - node_type = node_type.substring(0, 7); - - // Get the image information for current node - let imageStore = imageMapper.default; - var mappedImage = (_.isFunction(imageStore[node_type]) && - imageStore[node_type].apply(undefined, [data])) || - imageStore[node_type] || { - 'image': 'ex_unknown.svg', - 'image_text': node_type, - }; - - data['image'] = mappedImage['image']; - data['image_text'] = mappedImage['image_text']; - - if ('Actual Total Time' in data && 'Actual Loops' in data) { - data['inclusive'] = Math.ceil10( - data['Actual Total Time'], -3 - ); - data['exclusive'] = data['inclusive']; - data['inclusive_factor'] = data['inclusive'] / ( - data['total_time'] || data['Actual Total Time'] - ); - - if (data['inclusive_factor'] <= 0.1) { - data['inclusive_flag'] = '1'; - } else if (data['inclusive_factor'] < 0.5) { - data['inclusive_flag'] = '2'; - } else if (data['inclusive_factor'] <= 0.9) { - data['inclusive_flag'] = '3'; - } else { - data['inclusive_flag'] = '4'; - } - } - - if ('Actual Rows' in data && 'Plan Rows' in data) { - if ( - data['Actual Rows'] === 0 || data['Actual Rows'] > data['Plan Rows'] - ) { - data['rowsx'] = data['Plan Rows'] === 0 ? 0 : - (data['Actual Rows'] / data['Plan Rows']); - data['rowsx_direction'] = 'negative'; - } else { - data['rowsx'] = data['Actual Rows'] === 0 ? 0 : ( - data['Plan Rows'] / data['Actual Rows'] - ); - data['rowsx_direction'] = 'positive'; - } - - if (data['rowsx'] <= 10) { - data['rowsx_flag'] = '1'; - } else if (data['rowsx'] <= 100 ) { - data['rowsx_flag'] = '2'; - } else if (data['rowsx'] <= 1000 ) { - data['rowsx_flag'] = '3'; - } else { - data['rowsx_flag'] = '4'; - } - - if('loops' in data) { - data['rowsx'] = Math.ceil10(data['rowsx'] / data['loops'] || 1, -2); - } else { - data['rowsx'] = Math.ceil10(data['rowsx'], -2); - } - } - - // Start calculating xpos, ypos, width and height for child plans if any - if ('Plans' in data) { - var obj = this, - inclusive; - - data['width'] += offsetX; - - _.each(data['Plans'], function(p) { - var level = _.clone(lvl), - plan = obj._createSame(); - - level.push(idx); - plan.set(plan.parse(_.extend( - p, { - 'level': level, - xpos: xpos - offsetX, - ypos: ypos, - total_time: data['total_time'] || data['Actual Total Time'], - parent_node: lvl.join('_'), - loops: data['Actual Loops'] - }), _opt)); - - if (maxChildWidth < plan.get('width')) { - maxChildWidth = plan.get('width'); - } - - if ('exclusive' in data) { - inclusive = plan.get('inclusive'); - if (inclusive && inclusive < data['exclusive']) { - data['exclusive'] -= inclusive; - } - } - - var childHeight = plan.get('height'); - - if (idx !== 1) { - data['height'] = data['height'] + childHeight + offsetY; - } else if (childHeight > data['height']) { - data['height'] = childHeight; - } - ypos += childHeight + offsetY; - - plans.push(plan); - idx++; - }); - } else{ - if('loops' in data && 'exclusive' in data) { - data['inclusive'] = Math.ceil10(data['Actual Total Time'] / data['loops'] || 1, -3); - data['exclusive'] = data['inclusive']; - } - } - - if ('exclusive' in data) { - data['exclusive'] = Math.ceil10(data['exclusive'], -3); - data['exclusive_factor'] = ( - data['exclusive'] / (data['total_time'] || data['Actual Total Time']) - ); - - if (data['exclusive_factor'] <= 0.1) { - data['exclusive_flag'] = '1'; - } else if (data['exclusive_factor'] < 0.5) { - data['exclusive_flag'] = '2'; - } else if (data['exclusive_factor'] <= 0.9) { - data['exclusive_flag'] = '3'; - } else { - data['exclusive_flag'] = '4'; - } - } - - // Final Width and Height of current node - data['width'] += maxChildWidth; - data['Plans'] = plans; - - return data; - }, - - getLabel: function() { - return this.get('Schema') == undefined ? - this.get('image_text') : - (this.get('Schema') + '.' + this.get('image_text')); - }, - - // Draw image, its name and its tooltip - draw: function( - s, xpos, ypos, pXpos, pYpos, graphContainer, toolTipContainer, - _ctx - ) { - var g = s.g(); - var currentXpos = xpos + this.get('xpos'), - currentYpos = ypos + this.get('ypos'), - isSubPlan = (this.get('Parent Relationship') === 'SubPlan'); - - var planData = this.toJSON(); - var colorFg = getComputedStyle(document.documentElement).getPropertyValue('--color-fg'); - - _nodeExplainTableData(planData, _ctx); - - // Draw the subplan rectangle - if (isSubPlan) { - g.rect( - currentXpos - this.get('width') + pWIDTH + xMargin, - currentYpos - this.get('height') + pHEIGHT + yMargin - TXT_ALIGN, - this.get('width') - xMargin, - this.get('height') + (currentYpos - yMargin), - 5 - ).attr({ - stroke: '#444444', - 'strokeWidth': 1.2, - fill: 'gray', - fillOpacity: 0.2, - 'pointer-events': 'none', - }); - - // Provide subplan name - g.text( - currentXpos + pWIDTH - (this.get('width') / 2) - xMargin, - currentYpos + pHEIGHT - (this.get('height') / 2) - yMargin, - this.get('Subplan Name') - ).attr({ - fontSize: TXT_SIZE, - 'text-anchor': 'start', - fill: 'red', - }); - } - - this._drawImage( - s, g, pgExplain.prefix + this.get('image'), currentXpos, currentYpos, - graphContainer, toolTipContainer, _ctx - ); - - - // Draw text below the node - var node_label = this.getLabel(); - g.multitext( - currentXpos + (pWIDTH / 2) + TXT_ALIGN, - currentYpos + pHEIGHT - TXT_ALIGN, - node_label, - 150, { - 'font-size': TXT_SIZE, - 'text-anchor': 'middle', - 'fill': colorFg, - } - ); - - // Draw Arrow to parent only its not the first node - if (!_.isUndefined(pYpos)) { - var startx = currentXpos + pWIDTH; - var starty = currentYpos + (pHEIGHT / 2); - var endx = pXpos - ARROW_WIDTH; - var endy = pYpos + (pHEIGHT / 2); - var start_cost = this.get('Startup Cost'), - total_cost = this.get('Total Cost'); - var arrow_size = DEFAULT_ARROW_SIZE; - - // Calculate arrow width according to cost of a particular plan - if (start_cost != undefined && total_cost != undefined) { - arrow_size = Math.round(Math.log((start_cost + total_cost) / 2 + start_cost)); - if (arrow_size < 1) { - arrow_size = 1; - } else if (arrow_size > 10) { - arrow_size = 10; - } - } - - var arrow_view_box = [0, 0, 2 * ARROW_WIDTH, 2 * ARROW_HEIGHT]; - var opts = { - stroke: colorFg, - strokeWidth: arrow_size + 2, - }, - subplanOpts = { - stroke: colorFg, - strokeWidth: arrow_size + 2, - }, - arrowOpts = { - viewBox: arrow_view_box.join(' '), - fill: colorFg, - }; - - // Draw an arrow from current node to its parent - this.drawPolyLine( - g, startx, starty, endx, endy, - isSubPlan ? subplanOpts : opts, arrowOpts - ); - } - - var plans = this.get('Plans'); - - // Draw nodes for current plan's children - _.each(plans, function(p) { - p.draw( - s, xpos, ypos, currentXpos, currentYpos, graphContainer, - toolTipContainer, _ctx - ); - }); - }, - - _drawImage: function( - s, g, image_url, startX, startY, graphContainer, toolTipContainer /*, - _ctx - */ - ) { - this.drawImage( - g, image_url, startX, startY, graphContainer, toolTipContainer - ); - }, - - /* - * Required to parse and include non-default params of - * plan into backbone model - */ - toJSON: function(non_recursive) { - var res = Backbone.Model.prototype.toJSON.apply(this, arguments); - - if (non_recursive) { - delete res['Plans']; - } else { - var plans = []; - _.each(res['Plans'], function(p) { - plans.push(p.toJSON()); - }); - res['Plans'] = plans; - } - return res; - }, - - // Draw an arrow to parent node - drawPolyLine: function(g, startX, startY, endX, endY, opts, arrowOpts) { - // Calculate end point of first starting straight line (startx1, starty1) - // Calculate start point of 2nd straight line (endx1, endy1) - var midX1 = startX + ((endX - startX) / 3), - midX2 = startX + (2 * ((endX - startX) / 3)); - - //create arrow head - var arrow = g.polygon( - [0, ARROW_HEIGHT, - (ARROW_WIDTH / 2), ARROW_HEIGHT, - (ARROW_HEIGHT / 4), 0, - 0, ARROW_WIDTH, - ] - ).transform('r90'); - var marker = arrow.marker( - 0, 0, ARROW_WIDTH, ARROW_HEIGHT, 0, (ARROW_WIDTH / 2) - ).attr(arrowOpts); - - // First straight line - g.line( - startX, startY, midX1, startY - ).attr(opts); - - // Diagonal line - g.line( - midX1 - 1, startY, midX2, endY - ).attr(opts); - - // Last straight line - var line = g.line( - midX2, endY, endX, endY - ).attr(opts); - line.attr({ - markerEnd: marker, - }); - }, - - drawImage: function( - g, image_content, currentXpos, currentYpos, graphContainer, - toolTipContainer, downloadSVGFile=false - ) { - // Draw the actual image for current node - var image = g.image( - image_content, - currentXpos + (pWIDTH - IMAGE_WIDTH) / 2, - currentYpos + (pHEIGHT - IMAGE_HEIGHT) / 2, - IMAGE_WIDTH, - IMAGE_HEIGHT - ); - image.attr({ - style: 'cursor: pointer', - class: 'image-node', - }); - - // Draw tooltip - var image_data = this.toJSON(), - nodeLabel = this.getLabel(); - - if (downloadSVGFile) { - var title = ''; - _.each(image_data, function (value, key) { - if ( - key !== 'image' && - key !== 'Plans' && - key !== 'level' && - key !== 'image' && - key !== 'image_text' && - key !== 'xpos' && - key !== 'ypos' && - key !== 'width' && - key !== 'height' - ) { - title += `${key}: ${value}\n`; - } - }); - - title += ''; - - image.append(Snap.parse(title)); - - } - - image.click(() => { - // Empty the tooltip content if it has any and add new data - let toolTipBody = toolTipContainer.find('.details-body'); - let toolTipTitle = toolTipContainer.find('.details-title'); - toolTipTitle.text(nodeLabel); - - toolTipBody.empty(); - - // Remove the title content so that we can show our custom build tooltips. - image.node.textContent = ''; - - var tooltipTable = $(` -
    - -
    ` - ).appendTo(toolTipBody); - var tooltip = tooltipTable.find('tbody'); - - _.each(image_data, function(value, key) { - if (key !== 'image' && key !== 'Plans' && - key !== 'level' && key !== 'image' && - key !== 'image_text' && key !== 'xpos' && - key !== 'ypos' && key !== 'width' && - key !== 'height') { - key = _.escape(key); - value = _.escape(value); - tooltip.append(` - - ${key} - ${value} - - `); - } - }); - toolTipContainer.removeClass('d-none'); - toolTipBody.scrollTop(0); - }); - }, - }); - - /* - * NOTE: embedding using .toDataURL() method hits the performance of the - * plan rendering a lot, that is why we have written seprate Model for the same - * which is used only when downloading of SVG is called - */ - // We override the PlanModel's draw() function so that we can embbed all the - // svg in to main one SVG so that we can download it. - let DownloadPlanModel = PlanModel.extend({ - _createSame: function() { - return new DownloadPlanModel({parse: true}); - }, - - _drawImage: function ( - s, g, image_url, startX, startY, graphContainer, toolTipContainer, _ctx - ) { - /* Check the current browser, if it is Internet Explorer then we will not - * embed the SVG files for download feature as we are not bale to figure - * out the solution for IE. - */ - - var current_browser = pgAdmin.Browser.get_browser(); - if (current_browser.name === 'IE' || ( - current_browser.name === 'Safari' && - parseInt(current_browser.version) < 10 - )) { - this.drawImage( - g, image_url, startX, startY, graphContainer, toolTipContainer - ); - } else { - /* This function is a callback function called when we load any svg - * file using Snap. In this function we append the SVG binary data to - * the new temporary Snap object and then embedded it to the original - * Snap() object. - */ - var that = this; - var onSVGLoaded = function(data) { - var svg_image = Snap(); - svg_image.append(data); - var downloadSVGFile = true; - - that.drawImage( - g, svg_image.toDataURL(), startX, startY, graphContainer, - toolTipContainer, downloadSVGFile - ); - - // This attribute is required to download the file as SVG image. - s.parent().attr({ - 'xmlns:xlink':'http://www.w3.org/1999/xlink', - }); - setTimeout(() => { - _ctx._onImageDownloaded(); - }, 100); - }; - - var svg_file = pgExplain.prefix + this.get('image'); - - // Load the SVG file for explain plan - Snap.load(svg_file, onSVGLoaded); - } - }, - }); - - // Main backbone model to store JSON object - var MainPlanModel = Backbone.Model.extend({ - defaults: { - 'Plan': undefined, - xpos: 0, - ypos: 0, - }, - initialize: function() { - this.set('Plan', new PlanModel()); - this.set('Statistics', new StatisticsModel()); - }, - - // Parse the JSON data and fetch its children plans - parse: function(data, _opt) { - - if (data && 'Plan' in data) { - var plan = this.get('Plan'); - plan.set(plan.parse( - _.extend( - data['Plan'], { - xpos: 0, - ypos: 0, - loops: 1 - }), _opt - )); - - data['xpos'] = 0; - data['ypos'] = 0; - data['width'] = plan.get('width') + (xMargin * 2); - data['height'] = plan.get('height') + (yMargin * 4); - - delete data['Plan']; - } - - var statistics = this.get('Statistics'); - if (data && 'JIT' in data) { - statistics.set('JIT', data['JIT']); - delete data ['JIT']; - } - - if (data && 'Triggers' in data) { - statistics.set('Triggers', data['Triggers']); - delete data ['Triggers']; - } - - if(data) { - let summKeys = ['Planning Time', 'Execution Time'], - summary = {}; - - summKeys.forEach((key)=>{ - if (key in data) { - summary[key] = data[key]; - } - }); - - statistics.set('Summary', summary); - } - if (data && 'Settings' in data) { - statistics.set('Settings', data['Settings']); - delete data ['Settings']; - } - - return data; - }, - - toJSON: function() { - var res = Backbone.Model.prototype.toJSON.apply(this, arguments); - - if (res.Plan) { - res.Plan = res.Plan.toJSON(); - } - - return res; - }, - - draw: function(s, xpos, ypos, graphContainer, toolTipContainer, _ctx) { - var g = s.g(); - var colorBg = getComputedStyle(document.documentElement).getPropertyValue('--color-bg'); - - //draw the border - g.rect( - 0, 0, this.get('width') - 10, this.get('height') - 10, 5 - ).attr({ - fill: colorBg, - }); - - var plan = this.get('Plan'); - - // Draw explain graph - plan.draw( - g, xpos, ypos, undefined, undefined, graphContainer, toolTipContainer, - _ctx - ); - - //Set the Statistics as tooltip - var statistics = this.get('Statistics'); - statistics.set_statistics(toolTipContainer); - }, - }); - - var _createContainer = function() { - _createContainer.cnt = (_createContainer.cnt || 0) + 1; - let id = _createContainer.cnt, - createTab = (_idx, _type, _label, _active) => { - return [ - '
    ', - ].join(''); - }, - createTabPanel = (_type, _active, _extraClasses) => { - return [ - '
    `, - '
    ', - ].join(''); - }; - return $([ - '
    ', - '
    ', - ' ', - '
    ', - createTabPanel('graphical', true, 'w-100 h-100 p-0'), - createTabPanel('table', false, 'p-0'), - createTabPanel('statistics', false, ''), - '
    ', - '
    ', - '
    ', - '
    ', - ].join('')); - }; - - // Parse and draw full graphical explain - _.extend(pgExplain, { - // Assumption container is a jQuery object - DrawJSONPlan: function(container, plan, isDownload, _ctx) { - let self = this; - require.ensure(['snap.svg'], function(require) { - var module = require('snap.svg'); - initSnap(module); - self.goForDraw(container, plan, isDownload, _ctx); - }, function(error){ - throw(error); - }, 'snapsvg'); - }, - - // Assumption container is a jQuery object - goForDraw: function(container, plan, isDownload, _ctx) { - var ctx = _.extend(_ctx || {}, { - totalNodes: 0, - totalDownloadedNodes: 0, - isDownloaded: 0, - }); - - container.empty() - .attr('el', 'sm').addClass('pg-no-overflow pg-el-container'); - - var explainContainer = _createContainer(), - explainTable = _createExplainTable(), - statisticsTables = _createStatisticsTables(), - graphicalContainer = explainContainer.find( - '[data-explain-tabpanel=graphical]' - ), - tableContainer = explainContainer.find( - '[data-explain-tabpanel=table]' - ); - - ctx.currentTab = container.find( - '.nav-link[aria-selected=true]' - ).attr('data-explain-role'); - - explainContainer.appendTo(container); - explainTable.appendTo(tableContainer); - statisticsTables.appendTo(explainContainer.find( - '[data-explain-tabpanel=statistics]' - )); - - var orignalPlan = $.extend(true, [], plan); - var curr_zoom_factor = 1.0; - - var zoomArea = $('
    ', { - class: 'pg-explain-zoom-area btn-group btn-group-sm', - role: 'group', - }).appendTo(graphicalContainer), - zoomInBtn = $('', { - class: 'btn btn-primary-icon pg-explain-zoom-btn', - title: gettext('Zoom in'), - 'aria-label': gettext('Zoom in'), - tabindex: 0, - }).appendTo(zoomArea).append( - $('', { - class: 'fa fa-search-plus', - })), - zoomToNormal = $('', { - class: 'btn btn-primary-icon pg-explain-zoom-btn', - title: gettext('Zoom to original'), - 'aria-label': gettext('Zoom to original'), - tabindex: 0, - }).appendTo(zoomArea).append( - $('', { - class: 'fa fa-arrows-alt', - })), - zoomOutBtn = $('', { - class: 'btn btn-primary-icon pg-explain-zoom-btn', - title: gettext('Zoom out'), - 'aria-label': gettext('Zoom out'), - tabindex: 0, - }).appendTo(zoomArea).append( - $('', { - class: 'fa fa-search-minus', - })); - - var downloadArea = $('
    ', { - class: 'pg-explain-download-area btn-group btn-group-sm', - role: 'group', - }).appendTo(graphicalContainer), - downloadBtn = $('', { - id: 'btn-explain-download', - class: 'btn btn-primary-icon pg-explain-download-btn', - title: gettext('Download'), - 'aria-label': gettext('Download'), - tabindex: 0, - disabled: function() { - var current_browser = pgAdmin.Browser.get_browser(); - if (current_browser.name === 'IE') { - this.title = 'Not supported for Internet Explorer'; - return true; - } - if (current_browser.name === 'Safari' && - parseInt(current_browser.version) < 10) { - this.title = 'Not supported for Safari version less than 10.1'; - return true; - } - return false; - }, - }).appendTo(downloadArea).append( - $('', { - class: 'fa fa-download', - })); - - var statsArea = $('
    ', { - class: 'pg-explain-stats-area btn-group btn-group-sm d-none', - role: 'group', - }).appendTo(graphicalContainer); - - $('', { - id: 'btn-explain-stats', - class: 'btn btn-primary-icon pg-explain-stats-btn', - title: gettext('Statistics'), - 'aria-label': gettext('Statistics'), - tabindex: 0, - }).appendTo(statsArea).append( - $('', { - class: 'fa fa-chart-line', - })); - - // Main div to be drawn all images on - var planDiv = $('
    ', { - class: 'pgadmin-explain-container w-100 h-100 overflow-auto', - }).appendTo(graphicalContainer); - planDiv.data('zoom-factor', curr_zoom_factor); - - var explainDetails = $( - `` - ).appendTo(graphicalContainer); - explainDetails.find('.details-close').on('click', ()=>{ - explainDetails.addClass('d-none'); - }); - - var w = 0, - h = yMargin; - - ctx._explainTable = { - rows: [], - statistics: { - tables: {}, - nodes: {}, - }, - }; - ctx._onImageDownloaded = () => { - ctx.totalDownloadedNodes++; - if (!ctx.isDownloaded && ctx.totalNodes === ctx.totalDownloadedNodes) { - ctx.isDownloaded = true; - var s = Snap( - `#${graphicalContainer.attr('id')} .pgadmin-explain-container svg` - ); - var today = new Date(); - var filename = 'explain_plan_' + today.getTime() + '.svg'; - svgDownloader.downloadSVG(s.toString(), filename); - } - }; - - // Lets regenrate the plan with embedded images - _.each(plan, function(p) { - var main_plan; - if(isDownload) { - // If user opt to download then we will use the DownloadPlanModel model - // so that it will embed the images while regenrating the plan - let DownloadMainPlanModel = MainPlanModel.extend({ - initialize: function() { - this.set('Plan', new DownloadPlanModel({ parse: true })); - this.set('Statistics', new StatisticsModel()); - }, - }); - main_plan = new DownloadMainPlanModel({ 'parse': true }); - } else { - main_plan = new MainPlanModel(); - } - - // Parse JSON data to backbone model - main_plan.set(main_plan.parse(p, {ctx: ctx})); - w = main_plan.get('width'); - h = main_plan.get('height'); - - var s = Snap(w, h), - $svg = $(s.node).detach(); - planDiv.append($svg); - main_plan.draw(s, w - xMargin, yMargin, planDiv, explainDetails, ctx); - - var initPanelWidth = planDiv.width(); - - /* - * Scale graph in case its width is bigger than panel width - * in which the graph is displayed - */ - if (initPanelWidth < w) { - var width_ratio = initPanelWidth / w; - - curr_zoom_factor = width_ratio; - curr_zoom_factor = curr_zoom_factor < MIN_ZOOM_FACTOR ? MIN_ZOOM_FACTOR : curr_zoom_factor; - curr_zoom_factor = curr_zoom_factor > INIT_ZOOM_FACTOR ? INIT_ZOOM_FACTOR : curr_zoom_factor; - - let zoomInMatrix = new Snap.matrix(); - zoomInMatrix.scale(curr_zoom_factor, curr_zoom_factor); - - $svg.find('g').first().attr({ - transform: zoomInMatrix, - }); - $svg.attr({ - 'width': w * curr_zoom_factor, - 'height': h * curr_zoom_factor, - }); - planDiv.data('zoom-factor', curr_zoom_factor); - } - - zoomInBtn.on('click', function() { - curr_zoom_factor = ((curr_zoom_factor + ZOOM_RATIO) > MAX_ZOOM_FACTOR) ? MAX_ZOOM_FACTOR : (curr_zoom_factor + ZOOM_RATIO); - let zoomInMatrix = new Snap.matrix(); - zoomInMatrix.scale(curr_zoom_factor, curr_zoom_factor); - - $svg.find('g').first().attr({ - transform: zoomInMatrix, - }); - $svg.attr({ - 'width': w * curr_zoom_factor, - 'height': h * curr_zoom_factor, - }); - planDiv.data('zoom-factor', curr_zoom_factor); - }); - - zoomOutBtn.on('click', function() { - curr_zoom_factor = ((curr_zoom_factor - ZOOM_RATIO) < MIN_ZOOM_FACTOR) ? MIN_ZOOM_FACTOR : (curr_zoom_factor - ZOOM_RATIO); - let zoomInMatrix = new Snap.matrix(); - zoomInMatrix.scale(curr_zoom_factor, curr_zoom_factor); - - $svg.find('g').first().attr({ - transform: zoomInMatrix, - }); - $svg.attr({ - 'width': w * curr_zoom_factor, - 'height': h * curr_zoom_factor, - }); - planDiv.data('zoom-factor', curr_zoom_factor); - }); - - zoomToNormal.on('click', function() { - curr_zoom_factor = INIT_ZOOM_FACTOR; - let zoomInMatrix = new Snap.matrix(); - zoomInMatrix.scale(curr_zoom_factor, curr_zoom_factor); - - $svg.find('g').first().attr({ - transform: zoomInMatrix, - }); - $svg.attr({ - 'width': w * curr_zoom_factor, - 'height': h * curr_zoom_factor, - }); - planDiv.data('zoom-factor', curr_zoom_factor); - }); - - downloadBtn.on('click', function() { - pgExplain.DrawJSONPlan(container, orignalPlan, true); - planDiv.on('explain:svg:downloaded', function() { - ctx.totalDownloadedNodes++; - if (!ctx.isDownloaded && ctx.totalNodes === ctx.totalDownloadedNodes) { - ctx.isDownloaded = true; - s = Snap('.pgadmin-explain-container svg'); - var today = new Date(); - var filename = 'explain_plan_' + today.getTime() + '.svg'; - svgDownloader.downloadSVG(s.toString(), filename); - } - }); - }); - container.find('.image-node').tooltip({ - title: gettext('Click for details...'), - template: '', - }); - }); - - _renderExplainTable(ctx._explainTable, explainTable); - - _renderStatisticsTable(ctx._explainTable, statisticsTables); - - container.on('shown.bs.tab', function() { - ctx.currentTab = container.find( - '.nav-link[aria-selected=true]' - ).attr('data-explain-role'); - }); - }, - }); - - $(document) - .on('mouseenter', '.pga-ex-row.pga-ex-collapsible', function(ev) { - let $target = $(ev.currentTarget); - - $target.parent().find( - '[data-parent=' + $target.attr('data-ex-id') + - '] > td.pg-ex-highlighter > i' - ).removeClass('invisible'); - }) - .on('mouseleave', '.pga-ex-row.pga-ex-collapsible', function(ev) { - let $target = $(ev.currentTarget); - - $target.parent().find( - '.pga-ex-row[data-parent=' + $target.attr('data-ex-id') + - '] > td.pg-ex-highlighter > i' - ).addClass('invisible'); - }) - .on('click', '.pga-ex-row.pga-ex-collapsible', function(ev) { - let $target = $(ev.currentTarget), - collapsed = ($target.attr('data-collapsed') === 'true'); - - if (collapsed) { - $target.parent().find( - '.pga-ex-row[data-parent^=' + $target.attr('data-ex-id') + ']' - ).removeClass('d-none').filter('[data-collapsed=true]').each( - function(idx, el) { - var $el = $(el); - $el.parent().find( - '.pga-ex-row[data-parent^=' + $el.attr('data-ex-id') + ']' - ).addClass('d-none'); - }); - $target.attr('data-collapsed', 'false'); - } else { - $target.parent().find( - '.pga-ex-row[data-parent^=' + $target.attr('data-ex-id') + ']' - ).addClass('d-none'); - $target.attr('data-collapsed', 'true'); - } - }); - - return pgExplain; -}); diff --git a/web/pgadmin/misc/static/explain/js/explain_statistics.js b/web/pgadmin/misc/static/explain/js/explain_statistics.js deleted file mode 100644 index c361c107f..000000000 --- a/web/pgadmin/misc/static/explain/js/explain_statistics.js +++ /dev/null @@ -1,127 +0,0 @@ -///////////////////////////////////////////////////////////// -// -// pgAdmin 4 - PostgreSQL Tools -// -// Copyright (C) 2013 - 2022, The pgAdmin Development Team -// This software is released under the PostgreSQL Licence -// -////////////////////////////////////////////////////////////// - -import $ from 'jquery'; -import Backbone from 'backbone'; -import gettext from 'sources/gettext'; - -// Backbone model for other statistics -let StatisticsModel = Backbone.Model.extend({ - defaults: { - JIT: [], - Triggers: [], - Summary: {}, - }, - - explainToolTip: function(key, value, tooltip) { - key = _.escape(key); - value = _.escape(value); - tooltip.append(` - - ${key} - ${value} - - `); - }, - - set_statistics: function(toolTipContainer) { - var self= this, - jit_stats = this.get('JIT'), - triggers_stats = this.get('Triggers'), - summary = this.get('Summary'); - - if (Object.keys(jit_stats).length > 0 || - Object.keys(triggers_stats).length > 0 || - Object.keys(summary).length > 0) { - $('.pg-explain-stats-area').removeClass('d-none'); - } - - var tooltipTable = $(` - - -
    ` - ); - var tooltip = tooltipTable.find('tbody'); - - if (Object.keys(jit_stats).length > 0){ - tooltip.append('' + gettext('JIT:') + ''); - _.each(jit_stats, function(value, key) { - self.explainToolTip(key, value, tooltip); - }); - } - - if (Object.keys(triggers_stats).length > 0){ - tooltip.append('' + gettext('Triggers:') + ''); - _.each(triggers_stats, function(triggers, key_id) { - if (triggers instanceof Object) { - _.each(triggers, function(value, key) { - if (key === 'Trigger Name') { - key = _.escape(key); - value = _.escape(value); - tooltip.append(` - - ${key} - ${value} - - `); - } else { - key = _.escape(key); - value = _.escape(value); - tooltip.append(` - - ${key} - ${value} - - `); - } - }); - } - else { - key_id = _.escape(key_id); - triggers = _.escape(triggers); - tooltip.append(` - - ${key_id} - ${triggers} - - `); - } - }); - } - - if (Object.keys(summary).length > 0){ - tooltip.append('' + gettext('Summary:') + ''); - _.each(summary, function(value, key) { - self.explainToolTip(key, value, tooltip); - }); - } - - $('.pg-explain-stats-area').off('click').on('click', () => { - // Empty the tooltip content if it has any and add new data - - if (Object.keys(jit_stats).length == 0 && - Object.keys(triggers_stats).length == 0 && - Object.keys(summary).length == 0) { - return; - } - - let toolTipBody = toolTipContainer.find('.details-body'); - let toolTipTitle = toolTipContainer.find('.details-title'); - toolTipTitle.text('Statistics'); - - toolTipBody.empty(); - toolTipBody.append(tooltipTable); - - toolTipContainer.removeClass('d-none'); - toolTipBody.scrollTop(0); - }); - }, -}); - -module.exports = StatisticsModel; diff --git a/web/pgadmin/misc/static/explain/js/image_mapper.js b/web/pgadmin/misc/static/explain/js/image_mapper.js deleted file mode 100644 index 5fcec6c97..000000000 --- a/web/pgadmin/misc/static/explain/js/image_mapper.js +++ /dev/null @@ -1,300 +0,0 @@ -///////////////////////////////////////////////////////////// -// -// pgAdmin 4 - PostgreSQL Tools -// -// Copyright (C) 2013 - 2022, The pgAdmin Development Team -// This software is released under the PostgreSQL Licence -// -////////////////////////////////////////////////////////////// - -/* - * A map which is used to fetch the image to be drawn and - * text which will appear below it - */ - -let imageMapper = { - 'Aggregate': { - 'image': 'ex_aggregate.svg', - 'image_text': 'Aggregate', - }, - 'Append': { - 'image': 'ex_append.svg', - 'image_text': 'Append', - }, - 'Bitmap Index Scan': function(data) { - return { - 'image': 'ex_bmp_index.svg', - 'image_text': data['Index Name'], - }; - }, - 'Bitmap Heap Scan': function(data) { - return { - 'image': 'ex_bmp_heap.svg', - 'image_text': data['Relation Name'], - }; - }, - 'BitmapAnd': { - 'image': 'ex_bmp_and.svg', - 'image_text': 'Bitmap AND', - }, - 'BitmapOr': { - 'image': 'ex_bmp_or.svg', - 'image_text': 'Bitmap OR', - }, - 'CTE Scan': { - 'image': 'ex_cte_scan.svg', - 'image_text': 'CTE Scan', - }, - 'Function Scan': { - 'image': 'ex_result.svg', - 'image_text': 'Function Scan', - }, - 'Foreign Scan': { - 'image': 'ex_foreign_scan.svg', - 'image_text': 'Foreign Scan', - }, - 'Gather': { - 'image': 'ex_gather_motion.svg', - 'image_text': 'Gather', - }, - 'Gather Merge': { - 'image': 'ex_gather_merge.svg', - 'image_text': 'Gather Merge', - }, - 'Group': { - 'image': 'ex_group.svg', - 'image_text': 'Group', - }, - 'GroupAggregate': { - 'image': 'ex_aggregate.svg', - 'image_text': 'Group Aggregate', - }, - 'Hash': { - 'image': 'ex_hash.svg', - 'image_text': 'Hash', - }, - 'Hash Join': function(data) { - if (!data['Join Type']) return { - 'image': 'ex_join.svg', - 'image_text': 'Join', - }; - switch (data['Join Type']) { - case 'Anti': - return { - 'image': 'ex_hash_anti_join.svg', - 'image_text': 'Hash Anti Join', - }; - case 'Semi': - return { - 'image': 'ex_hash_semi_join.svg', - 'image_text': 'Hash Semi Join', - }; - default: - return { - 'image': 'ex_hash.svg', - 'image_text': String('Hash ' + data['Join Type'] + ' Join'), - }; - } - }, - 'HashAggregate': { - 'image': 'ex_aggregate.svg', - 'image_text': 'Hash Aggregate', - }, - 'Index Only Scan': function(data) { - return { - 'image': 'ex_index_only_scan.svg', - 'image_text': data['Index Name'], - }; - }, - 'Index Scan': function(data) { - return { - 'image': 'ex_index_scan.svg', - 'image_text': data['Index Name'], - }; - }, - 'Index Scan Backword': { - 'image': 'ex_index_scan.svg', - 'image_text': 'Index Backward Scan', - }, - 'Limit': { - 'image': 'ex_limit.svg', - 'image_text': 'Limit', - }, - 'LockRows': { - 'image': 'ex_lock_rows.svg', - 'image_text': 'Lock Rows', - }, - 'Materialize': { - 'image': 'ex_materialize.svg', - 'image_text': 'Materialize', - }, - 'Merge Append': { - 'image': 'ex_merge_append.svg', - 'image_text': 'Merge Append', - }, - 'Merge Join': function(data) { - switch (data['Join Type']) { - case 'Anti': - return { - 'image': 'ex_merge_anti_join.svg', - 'image_text': 'Merge Anti Join', - }; - case 'Semi': - return { - 'image': 'ex_merge_semi_join.svg', - 'image_text': 'Merge Semi Join', - }; - default: - return { - 'image': 'ex_merge.svg', - 'image_text': String('Merge ' + data['Join Type'] + ' Join'), - }; - } - }, - 'ModifyTable': function(data) { - switch (data['Operation']) { - case 'Insert': - return { - 'image': 'ex_insert.svg', - 'image_text': 'Insert', - }; - case 'Update': - return { - 'image': 'ex_update.svg', - 'image_text': 'Update', - }; - case 'Delete': - return { - 'image': 'ex_delete.svg', - 'image_text': 'Delete', - }; - } - }, - 'Named Tuplestore Scan': { - 'image': 'ex_named_tuplestore_scan.svg', - 'image_text': 'Named Tuplestore Scan', - }, - 'Nested Loop': function(data) { - switch (data['Join Type']) { - case 'Anti': - return { - 'image': 'ex_nested_loop_anti_join.svg', - 'image_text': 'Nested Loop Anti Join', - }; - case 'Semi': - return { - 'image': 'ex_nested_loop_semi_join.svg', - 'image_text': 'Nested Loop Semi Join', - }; - default: - return { - 'image': 'ex_nested.svg', - 'image_text': 'Nested Loop ' + data['Join Type'] + ' Join', - }; - } - }, - 'ProjectSet': { - 'image': 'ex_projectset.svg', - 'image_text': 'ProjectSet', - }, - 'Recursive Union': { - 'image': 'ex_recursive_union.svg', - 'image_text': 'Recursive Union', - }, - 'Result': { - 'image': 'ex_result.svg', - 'image_text': 'Result', - }, - 'Sample Scan': { - 'image': 'ex_scan.svg', - 'image_text': 'Sample Scan', - }, - 'Scan': { - 'image': 'ex_scan.svg', - 'image_text': 'Scan', - }, - 'Seek': { - 'image': 'ex_seek.svg', - 'image_text': 'Seek', - }, - 'SetOp': function(data) { - let strategy = data['Strategy'], - command = data['Command']; - - if (strategy == 'Hashed') { - if (command.startsWith('Intersect')) { - if (command == 'Intersect All') - return { - 'image': 'ex_hash_setop_intersect_all.svg', - 'image_text': 'Hashed Intersect All', - }; - return { - 'image': 'ex_hash_setop_intersect.svg', - 'image_text': 'Hashed Intersect', - }; - } else if (command.startsWith('Except')) { - if (command == 'Except All') - return { - 'image': 'ex_hash_setop_except_all.svg', - 'image_text': 'Hashed Except All', - }; - return { - 'image': 'ex_hash_setop_except.svg', - 'image_text': 'Hash Except', - }; - } - return { - 'image': 'ex_hash_setop_unknown.svg', - 'image_text': 'Hashed SetOp Unknown', - }; - } - return { - 'image': 'ex_setop.svg', - 'image_text': 'SetOp', - }; - }, - 'Seq Scan': function(data) { - return { - 'image': 'ex_scan.svg', - 'image_text': data['Relation Name'], - }; - }, - 'Subquery Scan': { - 'image': 'ex_subplan.svg', - 'image_text': 'SubQuery Scan', - }, - 'Sort': { - 'image': 'ex_sort.svg', - 'image_text': 'Sort', - }, - 'Tid Scan': { - 'image': 'ex_tid_scan.svg', - 'image_text': 'Tid Scan', - }, - 'Table Function Scan': { - 'image': 'ex_table_func_scan.svg', - 'image_text': 'Table Function Scan', - }, - 'Unique': { - 'image': 'ex_unique.svg', - 'image_text': 'Unique', - }, - 'Values Scan': { - 'image': 'ex_values_scan.svg', - 'image_text': 'Values Scan', - }, - 'WindowAgg': { - 'image': 'ex_window_aggregate.svg', - 'image_text': 'Window Aggregate', - }, - 'WorkTable Scan': { - 'image': 'ex_worktable_scan.svg', - 'image_text': 'WorkTable Scan', - }, - 'Undefined': { - 'image': 'ex_unknown.svg', - 'image_text': 'Undefined', - }, -}; - -export default imageMapper; diff --git a/web/pgadmin/misc/static/explain/js/svg_downloader.js b/web/pgadmin/misc/static/explain/js/svg_downloader.js deleted file mode 100644 index bf1728a84..000000000 --- a/web/pgadmin/misc/static/explain/js/svg_downloader.js +++ /dev/null @@ -1,30 +0,0 @@ -///////////////////////////////////////////////////////////// -// -// pgAdmin 4 - PostgreSQL Tools -// -// Copyright (C) 2013 - 2022, The pgAdmin Development Team -// This software is released under the PostgreSQL Licence -// -////////////////////////////////////////////////////////////// - -let svgDownloader = { - blobURL: function(content, contentType) { - var blob = new Blob([content], {type: contentType}); - return (window.URL || window.webkitURL).createObjectURL(blob); - }, - - downloadSVG: function(content, fileName) { - // Safari xlink NS issue fixblobURL - content = content.replace(/NS\d+:href/gi, 'xlink:href'); - - var svgURL = this.blobURL(content, 'image/svg+xml'); - var newElement = document.createElement('a'); - newElement.href = svgURL; - newElement.setAttribute('download', fileName); - document.body.appendChild(newElement); - newElement.click(); - document.body.removeChild(newElement); - }, -}; - -export default svgDownloader; diff --git a/web/pgadmin/misc/static/explain/scss/_explain.scss b/web/pgadmin/misc/static/explain/scss/_explain.scss deleted file mode 100644 index 458dca075..000000000 --- a/web/pgadmin/misc/static/explain/scss/_explain.scss +++ /dev/null @@ -1,146 +0,0 @@ -.pgadmin-explain-details { - min-width: 200px; - max-width: 300px; - position: absolute; - top: 0.25rem; - bottom: 0.25rem; - right: 0.25rem; - border-color: $popover-border-color; - box-shadow: $popover-box-shadow; - word-break: break-all; - display: flex; - flex-direction: column; - z-index: 99; - - .details-header { - padding: 0.25rem; - font-weight: unset; - } - - .details-body { - overflow: auto; - flex-grow: 1; - } -} - - -.sql-editor-explain { - .backform-tab { - .tab-content { - bottom: 0.5rem; - background-color: $color-bg; - - div[data-explain-tabpanel=graphical] { - .btn-group { - position: absolute; - top: 4px; - margin-left: 4px; - - &.pg-explain-download-area.btn-group { - left: 90px; - } - - &.pg-explain-stats-area { - right: 4px; - } - - .btn { - font-size: 0.75rem; - } - - *:hover { - opacity: 1; - } - } - } - } - } -} - -div.tab-pane[data-explain-tabpanel=table] { - - border-bottom: $panel-border; - - td.pga-ex-exclusive-2, - td.pga-ex-inclusive-2, - td.pga-ex-rowsx-2 { - background-color: $explain-sev-2-bg; - color: $explain-sev-2-color; - } - - td.pga-ex-exclusive-3, - td.pga-ex-inclusive-3, - td.pga-ex-rowsx-3 { - background-color: $explain-sev-3-bg; - color: $explain-sev-3-color; - } - - td.pga-ex-exclusive-4, - td.pga-ex-inclusive-4, - td.pga-ex-rowsx-4 { - background-color: $explain-sev-4-bg; - color: $explain-sev-4-color; - } - - .pg-ex-subplans { - position: absolute; - margin-left: -20px; - margin-top: 3px; - font-weight: bold; - } - - table { - tr { - &[data-collapsed=true] { - td { - border-bottom: $table-hover-border; - border-bottom-style: dotted !important; - border-bottom-width: medium !important; - } - } - td { - li { - font-size: small; - opacity: 0.75; - overflow-wrap: break-word; - word-break: break-all; - overflow: visible; - white-space: pre-wrap; - word-wrap: break-word; - } - &.pg-ex-highlighter { - color: $color-fg; - } - } - &.pga-ex-collapsible { - td { - &.clickable { - cursor: pointer; - } - } - } - } - } -} - -div.tab-pane[data-explain-tabpanel=statistics] { - .badge { - cursor: initial; - } - table[for=per_table] { - tr { - &.table { - background-color: $color-gray-lighter; - - td:first-child { - font-weight: bold !important; - } - } - &.node { - td.name { - padding-left: 30px; - } - } - } - } -} diff --git a/web/regression/javascript/browser/generate_url_spec.js b/web/regression/javascript/browser/generate_url_spec.js index fc203f152..3b8275cfb 100644 --- a/web/regression/javascript/browser/generate_url_spec.js +++ b/web/regression/javascript/browser/generate_url_spec.js @@ -13,7 +13,7 @@ describe('generate_url', () => { describe('in collection', () => { let baseUrl, treeInfo, actionType, nodeType, pickFunction; beforeEach(() => { - baseUrl = 'http://base/and-extension/'; + baseUrl = 'https://base/and-extension/'; treeInfo = { treeNode1: { _id: 'an_id', @@ -29,7 +29,7 @@ describe('generate_url', () => { it('returns a correctly formatted URL', () => { let formattedUrl = generate_url(baseUrl, treeInfo, actionType, nodeType, pickFunction); - expect(formattedUrl).toEqual('http://base/and-extension/nodeType/actionType/an_id/'); + expect(formattedUrl).toEqual('https://base/and-extension/nodeType/actionType/an_id/'); }); describe('given there are multiple treeInfoItems', () => { @@ -51,14 +51,14 @@ describe('generate_url', () => { it('chooses the correct treeInfo', () => { let formattedUrl = generate_url(baseUrl, treeInfo, actionType, nodeType, pickFunction); - expect(formattedUrl).toEqual('http://base/and-extension/nodeType/actionType/a_third_id/an_id/'); + expect(formattedUrl).toEqual('https://base/and-extension/nodeType/actionType/a_third_id/an_id/'); }); }); }); describe('in node', () => { let baseUrl, treeInfo, actionType, nodeType, pickFunction, itemDataID; beforeEach(() => { - baseUrl = 'http://base/and-extension/'; + baseUrl = 'https://base/and-extension/'; treeInfo = { treeNode1: { _id: 'an_id', @@ -75,7 +75,7 @@ describe('generate_url', () => { it('returns a correctly formatted URL', () => { let formattedUrl = generate_url(baseUrl, treeInfo, actionType, nodeType, pickFunction, itemDataID); - expect(formattedUrl).toEqual('http://base/and-extension/nodeType/actionType/an_id/item1'); + expect(formattedUrl).toEqual('https://base/and-extension/nodeType/actionType/an_id/item1'); }); describe('given there are multiple treeInfoItems', () => { @@ -97,7 +97,7 @@ describe('generate_url', () => { it('chooses the correct treeInfo', () => { let formattedUrl = generate_url(baseUrl, treeInfo, actionType, nodeType, pickFunction, itemDataID); - expect(formattedUrl).toEqual('http://base/and-extension/nodeType/actionType/another_id/an_id/item1'); + expect(formattedUrl).toEqual('https://base/and-extension/nodeType/actionType/another_id/an_id/item1'); }); }); }); diff --git a/web/regression/javascript/misc/explain/explain_statistics_spec.js b/web/regression/javascript/misc/explain/explain_statistics_spec.js deleted file mode 100644 index b11e5fd25..000000000 --- a/web/regression/javascript/misc/explain/explain_statistics_spec.js +++ /dev/null @@ -1,106 +0,0 @@ -///////////////////////////////////////////////////////////// -// -// pgAdmin 4 - PostgreSQL Tools -// -// Copyright (C) 2013 - 2022, The pgAdmin Development Team -// This software is released under the PostgreSQL Licence -// -////////////////////////////////////////////////////////////// - -import StatisticsModel from '../../../../pgadmin/misc/static/explain/js/explain_statistics'; -import $ from 'jquery'; - -describe('ExplainStatistics', () => { - let statsModel; - let statsDiv; - let tooltipContainer; - - beforeEach(function() { - statsModel = new StatisticsModel(); - statsDiv = '
    '; - tooltipContainer = $( - `
    -
    -
    -
    -
    -
    ` - ); - }); - - describe('No Statistics', () => { - it('Statistics button should be hidden', () => { - $('body').append(statsDiv); - - statsModel.set('JIT', []); - statsModel.set('Triggers', []); - statsModel.set('Summary', {}); - statsModel.set_statistics(tooltipContainer); - - expect($('.pg-explain-stats-area').hasClass('d-none')).toEqual(true); - }); - }); - - let mouseClickAction = ()=> { - // Trigger mouse over event - var clickEvent = new $.Event('click'); - $('.pg-explain-stats-area').trigger(clickEvent); - - expect(tooltipContainer.hasClass('d-none')).toBe(false); - }; - - describe('JIT Statistics', () => { - beforeEach(function() { - $('body').append(statsDiv); - statsModel.set('JIT', [{'cost': '100'}]); - statsModel.set('Triggers', []); - statsModel.set_statistics(tooltipContainer); - }); - - it('Statistics button should be visible', () => { - expect($('.pg-explain-stats-area').hasClass('d-none')).toEqual(false); - }); - - it('Mouse click event should be trigger', () => { - mouseClickAction(); - }); - }); - - describe('Triggers Statistics', () => { - beforeEach(function() { - $('body').append(statsDiv); - statsModel.set('JIT', []); - statsModel.set('Triggers', [{'name': 'test_trigger'}]); - statsModel.set_statistics(tooltipContainer); - }); - - it('Statistics button should be visible', () => { - expect($('.pg-explain-stats-area').hasClass('d-none')).toEqual(false); - }); - - it('Mouse click event should be trigger', () => { - mouseClickAction(); - }); - }); - - describe('Summary', () => { - beforeEach(function() { - $('body').append(statsDiv); - statsModel.set('JIT', []); - statsModel.set('Triggers', []); - statsModel.set('Summary', { - 'Planning Time': 0.12, - 'Execution Time': 2.34, - }); - statsModel.set_statistics(tooltipContainer); - }); - - it('Statistics button should be visible', () => { - expect($('.pg-explain-stats-area').hasClass('d-none')).toEqual(false); - }); - - it('Mouse click event should be trigger', () => { - mouseClickAction(); - }); - }); -}); diff --git a/web/webpack.shim.js b/web/webpack.shim.js index 7f0a9c3c4..ded8b0dcf 100644 --- a/web/webpack.shim.js +++ b/web/webpack.shim.js @@ -203,7 +203,6 @@ var webpackShimConfig = { 'pgadmin.browser.utils': '/browser/js/utils', 'pgadmin.dashboard': path.join(__dirname, './pgadmin/dashboard/static/js/Dashboard'), 'pgadmin.help': path.join(__dirname, './pgadmin/help/static/js/help'), - 'pgadmin.misc.explain': path.join(__dirname, './pgadmin/misc/static/explain/js/explain'), 'pgadmin.misc.cloud': path.join(__dirname, './pgadmin/misc/cloud/static/js/cloud'), 'pgadmin.node.cast': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/casts/static/js/cast'), 'pgadmin.node.publication': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/publications/static/js/publication'),