From 5ed7015ebc92c161a15e0b959846286967142f3c Mon Sep 17 00:00:00 2001 From: Khushboo Vashi Date: Tue, 5 Apr 2016 16:14:10 +0100 Subject: [PATCH] Add support for functions and procedures. --- .../databases/schemas/functions/__init__.py | 1314 +++++++++++++++++ .../functions/static/img/coll-function.png | Bin 0 -> 349 bytes .../functions/static/img/coll-procedure.png | Bin 0 -> 337 bytes .../schemas/functions/static/img/function.png | Bin 0 -> 325 bytes .../functions/static/img/procedure.png | Bin 0 -> 322 bytes .../templates/function/css/function.css | 3 + .../templates/function/js/functions.js | 482 ++++++ .../function/pg/sql/9.1_plus/acl.sql | 35 + .../function/pg/sql/9.1_plus/create.sql | 53 + .../function/pg/sql/9.1_plus/delete.sql | 21 + .../pg/sql/9.1_plus/get_definition.sql | 11 + .../pg/sql/9.1_plus/get_languages.sql | 4 + .../function/pg/sql/9.1_plus/get_oid.sql | 17 + .../pg/sql/9.1_plus/get_out_types.sql | 6 + .../function/pg/sql/9.1_plus/get_schema.sql | 6 + .../function/pg/sql/9.1_plus/get_types.sql | 20 + .../function/pg/sql/9.1_plus/node.sql | 17 + .../function/pg/sql/9.1_plus/properties.sql | 31 + .../function/pg/sql/9.1_plus/update.sql | 105 ++ .../function/pg/sql/9.1_plus/variables.sql | 6 + .../function/pg/sql/9.2_plus/acl.sql | 35 + .../function/pg/sql/9.2_plus/create.sql | 57 + .../function/pg/sql/9.2_plus/delete.sql | 21 + .../pg/sql/9.2_plus/get_definition.sql | 11 + .../pg/sql/9.2_plus/get_languages.sql | 4 + .../function/pg/sql/9.2_plus/get_oid.sql | 17 + .../pg/sql/9.2_plus/get_out_types.sql | 6 + .../function/pg/sql/9.2_plus/get_schema.sql | 6 + .../function/pg/sql/9.2_plus/get_types.sql | 20 + .../function/pg/sql/9.2_plus/node.sql | 17 + .../function/pg/sql/9.2_plus/properties.sql | 31 + .../function/pg/sql/9.2_plus/update.sql | 114 ++ .../function/pg/sql/9.2_plus/variables.sql | 6 + .../function/pg/sql/9.5_plus/acl.sql | 35 + .../function/pg/sql/9.5_plus/create.sql | 57 + .../function/pg/sql/9.5_plus/delete.sql | 21 + .../pg/sql/9.5_plus/get_definition.sql | 11 + .../pg/sql/9.5_plus/get_languages.sql | 4 + .../function/pg/sql/9.5_plus/get_oid.sql | 17 + .../pg/sql/9.5_plus/get_out_types.sql | 6 + .../function/pg/sql/9.5_plus/get_schema.sql | 6 + .../function/pg/sql/9.5_plus/get_types.sql | 20 + .../function/pg/sql/9.5_plus/node.sql | 17 + .../function/pg/sql/9.5_plus/properties.sql | 31 + .../function/pg/sql/9.5_plus/update.sql | 114 ++ .../function/pg/sql/9.5_plus/variables.sql | 6 + .../function/ppas/sql/9.1_plus/acl.sql | 35 + .../function/ppas/sql/9.1_plus/create.sql | 53 + .../function/ppas/sql/9.1_plus/delete.sql | 21 + .../ppas/sql/9.1_plus/get_definition.sql | 11 + .../ppas/sql/9.1_plus/get_languages.sql | 4 + .../function/ppas/sql/9.1_plus/get_oid.sql | 17 + .../ppas/sql/9.1_plus/get_out_types.sql | 6 + .../function/ppas/sql/9.1_plus/get_schema.sql | 6 + .../function/ppas/sql/9.1_plus/get_types.sql | 20 + .../function/ppas/sql/9.1_plus/node.sql | 18 + .../function/ppas/sql/9.1_plus/properties.sql | 31 + .../function/ppas/sql/9.1_plus/update.sql | 105 ++ .../function/ppas/sql/9.1_plus/variables.sql | 6 + .../function/ppas/sql/9.2_plus/acl.sql | 35 + .../function/ppas/sql/9.2_plus/create.sql | 57 + .../function/ppas/sql/9.2_plus/delete.sql | 22 + .../ppas/sql/9.2_plus/get_definition.sql | 11 + .../ppas/sql/9.2_plus/get_languages.sql | 4 + .../function/ppas/sql/9.2_plus/get_oid.sql | 17 + .../ppas/sql/9.2_plus/get_out_types.sql | 6 + .../function/ppas/sql/9.2_plus/get_schema.sql | 6 + .../function/ppas/sql/9.2_plus/get_types.sql | 20 + .../function/ppas/sql/9.2_plus/node.sql | 18 + .../function/ppas/sql/9.2_plus/properties.sql | 31 + .../function/ppas/sql/9.2_plus/update.sql | 114 ++ .../function/ppas/sql/9.2_plus/variables.sql | 6 + .../function/ppas/sql/9.5_plus/acl.sql | 35 + .../function/ppas/sql/9.5_plus/create.sql | 57 + .../function/ppas/sql/9.5_plus/delete.sql | 21 + .../ppas/sql/9.5_plus/get_definition.sql | 11 + .../ppas/sql/9.5_plus/get_languages.sql | 4 + .../function/ppas/sql/9.5_plus/get_oid.sql | 17 + .../ppas/sql/9.5_plus/get_out_types.sql | 6 + .../function/ppas/sql/9.5_plus/get_schema.sql | 6 + .../function/ppas/sql/9.5_plus/get_types.sql | 20 + .../function/ppas/sql/9.5_plus/node.sql | 18 + .../function/ppas/sql/9.5_plus/properties.sql | 31 + .../function/ppas/sql/9.5_plus/update.sql | 114 ++ .../function/ppas/sql/9.5_plus/variables.sql | 6 + .../templates/procedure/js/procedures.js | 184 +++ .../procedure/ppas/sql/9.1_plus/acl.sql | 35 + .../procedure/ppas/sql/9.1_plus/create.sql | 33 + .../procedure/ppas/sql/9.1_plus/delete.sql | 21 + .../ppas/sql/9.1_plus/get_definition.sql | 12 + .../ppas/sql/9.1_plus/get_languages.sql | 4 + .../procedure/ppas/sql/9.1_plus/get_oid.sql | 17 + .../ppas/sql/9.1_plus/get_out_types.sql | 6 + .../ppas/sql/9.1_plus/get_schema.sql | 6 + .../procedure/ppas/sql/9.1_plus/get_types.sql | 20 + .../procedure/ppas/sql/9.1_plus/node.sql | 25 + .../ppas/sql/9.1_plus/properties.sql | 38 + .../procedure/ppas/sql/9.1_plus/update.sql | 82 + .../procedure/ppas/sql/9.1_plus/variables.sql | 6 + .../procedure/ppas/sql/9.2_plus/acl.sql | 35 + .../procedure/ppas/sql/9.2_plus/create.sql | 33 + .../procedure/ppas/sql/9.2_plus/delete.sql | 21 + .../ppas/sql/9.2_plus/get_definition.sql | 12 + .../ppas/sql/9.2_plus/get_languages.sql | 4 + .../procedure/ppas/sql/9.2_plus/get_oid.sql | 17 + .../ppas/sql/9.2_plus/get_out_types.sql | 6 + .../ppas/sql/9.2_plus/get_schema.sql | 6 + .../procedure/ppas/sql/9.2_plus/get_types.sql | 20 + .../procedure/ppas/sql/9.2_plus/node.sql | 25 + .../ppas/sql/9.2_plus/properties.sql | 38 + .../procedure/ppas/sql/9.2_plus/update.sql | 78 + .../procedure/ppas/sql/9.2_plus/variables.sql | 6 + .../procedure/ppas/sql/9.5_plus/acl.sql | 35 + .../procedure/ppas/sql/9.5_plus/create.sql | 43 + .../procedure/ppas/sql/9.5_plus/delete.sql | 21 + .../ppas/sql/9.5_plus/get_definition.sql | 12 + .../ppas/sql/9.5_plus/get_languages.sql | 4 + .../procedure/ppas/sql/9.5_plus/get_oid.sql | 17 + .../ppas/sql/9.5_plus/get_out_types.sql | 6 + .../ppas/sql/9.5_plus/get_schema.sql | 6 + .../procedure/ppas/sql/9.5_plus/get_types.sql | 20 + .../procedure/ppas/sql/9.5_plus/node.sql | 25 + .../ppas/sql/9.5_plus/properties.sql | 38 + .../procedure/ppas/sql/9.5_plus/update.sql | 102 ++ .../procedure/ppas/sql/9.5_plus/variables.sql | 6 + 125 files changed, 4972 insertions(+) create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/coll-function.png create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/coll-procedure.png create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/function.png create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/procedure.png create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/css/function.css create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/js/functions.js create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/acl.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/create.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/delete.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_definition.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_languages.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_oid.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_out_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/node.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/properties.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/update.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/variables.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/acl.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/create.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/delete.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_definition.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_languages.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_oid.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_out_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/node.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/properties.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/update.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/variables.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/acl.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/create.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/delete.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_definition.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_languages.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_oid.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_out_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/node.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/properties.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/update.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/variables.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/acl.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/create.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/delete.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_definition.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_languages.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_oid.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_out_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/node.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/properties.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/update.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/variables.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/acl.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/create.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/delete.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_definition.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_languages.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_oid.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_out_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/node.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/properties.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/update.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/variables.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/acl.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/create.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/delete.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_definition.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_languages.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_oid.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_out_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/node.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/properties.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/update.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/variables.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/acl.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/create.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/delete.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_definition.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_languages.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_oid.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_out_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/node.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/properties.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/update.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/variables.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/acl.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/create.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/delete.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_definition.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_languages.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_oid.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_out_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/node.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/properties.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/update.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/variables.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/acl.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/create.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/delete.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_definition.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_languages.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_oid.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_out_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_schema.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_types.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/node.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/properties.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/update.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/variables.sql diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py new file mode 100644 index 000000000..8e6947f37 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py @@ -0,0 +1,1314 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2016, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + +"""Implements Functions/Procedures Node.""" + +import json +import sys +import traceback +import copy +import re +from flask import render_template, make_response, request, jsonify, \ + current_app, url_for +from flask.ext.babel import gettext +from functools import wraps +from pgadmin.utils.ajax import make_json_response, \ + make_response as ajax_response, internal_server_error, gone +from pgadmin.browser.utils import PGChildNodeView +from pgadmin.browser.collection import CollectionNodeModule +import pgadmin.browser.server_groups.servers.databases.schemas as schemas +from pgadmin.utils.ajax import precondition_required +from pgadmin.utils.driver import get_driver +from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \ + parse_priv_to_db +from pgadmin.browser.server_groups.servers.databases.schemas.utils import \ + SchemaChildModule, DataTypeReader +from config import PG_DEFAULT_DRIVER +from pgadmin.browser.server_groups.servers.databases.utils import \ + parse_sec_labels_from_db, parse_variables_from_db + +class FunctionModule(SchemaChildModule): + """ + class FunctionModule(SchemaChildModule): + + This class represents The Functions Module. + + Methods: + ------- + * __init__(*args, **kwargs) + - Initialize the Functions Module. + + * get_nodes(gid, sid, did, scid) + - Generate the Functions collection node. + + * node_inode(): + - Returns Functions node as leaf node. + + * script_load() + - Load the module script for Functions, when schema node is + initialized. + + * csssnippets() + - Returns a snippet of css. + """ + + NODE_TYPE = 'function' + COLLECTION_LABEL = gettext("Functions") + + def __init__(self, *args, **kwargs): + """ + Initialize the Function Module. + Args: + *args: + **kwargs: + """ + super(FunctionModule, self).__init__(*args, **kwargs) + + self.min_ver = 90100 + self.max_ver = None + self.server_type = None + + def get_nodes(self, gid, sid, did, scid): + """ + Generate Functions collection node. + """ + yield self.generate_browser_collection_node(scid) + + @property + def node_inode(self): + """ + Make the node as leaf node. + Returns: + False as this node doesn't have child nodes. + """ + return False + + @property + def script_load(self): + """ + Load the module script for Functions, when the + schema node is initialized. + """ + return schemas.SchemaModule.NODE_TYPE + + @property + def csssnippets(self): + """ + Returns a snippet of css + """ + snippets = [ + render_template("function/css/function.css") + ] + snippets.extend( + super(SchemaChildModule, self).csssnippets + ) + + return snippets + +blueprint = FunctionModule(__name__) + + +class FunctionView(PGChildNodeView, DataTypeReader): + """ + class FunctionView(PGChildNodeView) + + This class inherits PGChildNodeView to get the different routes for + the module. + + The class is responsible to Create, Read, Update and Delete operations for + the Functions. + + Methods: + ------- + * validate_request(f): + - Works as a decorator. + Validating request on the request of create, update and modified SQL. + + * module_js(): + - Overrides this property to define javascript for Functions node. + + * check_precondition(f): + - Works as a decorator. + - Checks database connection status. + - Attach connection object and template path. + + * list(gid, sid, did, scid): + - List the Functions. + + * nodes(gid, sid, did, scid): + - Returns all the Functions to generate Nodes in the browser. + + * properties(gid, sid, did, scid, fnid): + - Returns the Functions properties. + + * create(gid, sid, did, scid): + - Creates a new Functions object. + + * update(gid, sid, did, scid, fnid): + - Updates the Functions object. + + * delete(gid, sid, did, scid, fnid): + - Drops the Functions object. + + * sql(gid, sid, did, scid, fnid): + - Returns the SQL for the Functions object. + + * msql(gid, sid, did, scid, fnid=None): + - Returns the modified SQL. + + * dependents(gid, sid, did, scid, fnid): + - Returns the dependents for the Functions object. + + * dependencies(gid, sid, did, scid, fnid): + - Returns the dependencies for the Functions object. + + * get_languages(gid, sid, did, scid, fnid=None): + - Returns languages. + + * types(gid, sid, did, scid, fnid=None): + - Returns Data Types. + """ + + node_type = blueprint.node_type + + parent_ids = [ + {'type': 'int', 'id': 'gid'}, + {'type': 'int', 'id': 'sid'}, + {'type': 'int', 'id': 'did'}, + {'type': 'int', 'id': 'scid'} + ] + ids = [ + {'type': 'int', 'id': 'fnid'} + ] + + operations = dict({ + 'obj': [ + {'get': 'properties', 'delete': 'delete', 'put': 'update'}, + {'get': 'list', 'post': 'create'} + ], + 'delete': [{'delete': 'delete'}], + 'children': [{'get': 'children'}], + 'nodes': [{'get': 'node'}, {'get': 'nodes'}], + 'sql': [{'get': 'sql'}], + 'msql': [{'get': 'msql'}, {'get': 'msql'}], + 'stats': [{'get': 'statistics'}], + 'dependency': [{'get': 'dependencies'}], + 'dependent': [{'get': 'dependents'}], + 'module.js': [{}, {}, {'get': 'module_js'}], + 'get_types': [{'get': 'types'}, {'get': 'types'}], + 'get_languages': [{'get': 'get_languages'}, {'get': 'get_languages'}], + 'vopts': [{}, {'get': 'variable_options'}] + }) + + @property + def required_args(self): + """ + Returns Required arguments for functions node. + Where + Required Args: + name: Name of the Function + funcowner: Function Owner + pronamespace: Function Namespace + prorettypename: Function Return Type + lanname: Function Language Name + prosrc: Function Code + probin: Function Object File + """ + return [ + 'name', + 'funcowner', + 'pronamespace', + 'prorettypename', + 'lanname', + 'prosrc', + 'probin' + ] + + def validate_request(f): + """ + Works as a decorator. + Validating request on the request of create, update and modified SQL. + """ + + @wraps(f) + def wrap(self, **kwargs): + + data = {} + if request.data: + req = json.loads(request.data.decode()) + else: + req = request.args or request.form + + if 'fnid' not in kwargs: + + for arg in self.required_args: + if (arg not in req or req[arg] == '') or\ + (arg == 'probin' and req['lanname'] == 'c' + and (arg not in req or req[arg] == '')): + return make_json_response( + status=410, + success=0, + errormsg=gettext( + "Couldn't find the required parameter \ + (%s)." % arg + ) + ) + + try: + list_params = [] + if request.method == 'GET': + list_params = ['arguments', 'variables', 'proacl', + 'seclabels', 'acl'] + + for key in req: + if key in list_params and req[key] != '' \ + and req[key] is not None: + # Coverts string into python list as expected. + data[key] = json.loads(req[key]) + elif ( + key == 'proretset' or key == 'proisstrict' or + key == 'prosecdef' or key == 'proiswindow' or + key == 'proleakproof' + ): + data[key] = True if ( + req[key] == 'true' or req[key] is True)\ + else False if (req[key] == 'false' or + req[key] is False) else '' + else: + data[key] = req[key] + + except Exception as e: + return internal_server_error(errormsg=str(e)) + + self.request = data + return f(self, **kwargs) + + return wrap + + def module_js(self): + """ + Load JS file (functions.js) for this module. + """ + + return make_response( + render_template( + "function/js/functions.js", + _=gettext + ), + 200, {'Content-Type': 'application/x-javascript'} + ) + + def check_precondition(f): + """ + Works as a decorator. + Checks the database connection status. + Attaches the connection object and template path to the class object. + """ + + @wraps(f) + def wrap(*args, **kwargs): + self = args[0] + driver = get_driver(PG_DEFAULT_DRIVER) + self.manager = driver.connection_manager(kwargs['sid']) + + # Get database connection + self.conn = self.manager.connection(did=kwargs['did']) + + self.qtIdent = driver.qtIdent + self.qtLiteral = driver.qtLiteral + + if not self.conn.connected(): + return precondition_required( + gettext( + "Connection to the server has been lost!" + ) + ) + + ver = self.manager.version + + # Set template path for sql scripts depending + # on the server version. + self.template_path = "/".join([ + self.node_type + ]) + self.sql_template_path = "/".join([ + self.template_path, + self.manager.server_type, + 'sql', + '9.5_plus' if ver >= 90500 else + '9.2_plus' if ver >= 90200 else + '9.1_plus' + ]) + + return f(*args, **kwargs) + + return wrap + + @check_precondition + def list(self, gid, sid, did, scid): + """ + List all the Functions. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + """ + + SQL = render_template("/".join([self.sql_template_path, 'node.sql']), + scid=scid) + status, res = self.conn.execute_dict(SQL) + + if not status: + return internal_server_error(errormsg=res) + return ajax_response( + response=res['rows'], + status=200 + ) + + @check_precondition + def nodes(self, gid, sid, did, scid): + """ + Returns all the Functions to generate the Nodes. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + """ + + res = [] + SQL = render_template("/".join([self.sql_template_path, + 'node.sql']), scid=scid) + status, rset = self.conn.execute_2darray(SQL) + + if not status: + return internal_server_error(errormsg=rset) + + for row in rset['rows']: + res.append( + self.blueprint.generate_browser_node( + row['oid'], + scid, + row['name'], + icon="icon-" + self.node_type, + funcowner=row['funcowner'], + language=row['lanname'] + )) + + return make_json_response( + data=res, + status=200 + ) + + @check_precondition + def properties(self, gid, sid, did, scid, fnid=None): + """ + Returns the Function properties. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + fnid: Function Id + """ + + resp_data = self._fetch_properties(gid, sid, did, scid, fnid) + + return ajax_response( + response=resp_data, + status=200 + ) + + def _format_arguments_from_db(self, data): + """ + Create Argument list of the Function. + + Args: + data: Function Data + + Returns: + Function Arguments in the following format. + [ + {'proargtypes': 'integer', 'proargmodes: 'IN', + 'proargnames': 'column1', 'proargdefaultvals': 1}, {...} + ] + Where + Arguments: + proargtypes: Argument Types (Data Type) + proargmodes: Argument Modes [IN, OUT, INOUT, VARIADIC] + proargnames: Argument Name + proargdefaultvals: Default Value of the Argument + """ + proargtypes = [ptype for ptype in data['proargtypenames'].split(",")]\ + if data['proargtypenames'] else [] + proargmodes = data['proargmodes'] if data['proargmodes'] else [] + proargnames = data['proargnames'] if data['proargnames'] else [] + proargdefaultvals = [ptype for ptype in + data['proargdefaultvals'].split(",")] \ + if data['proargdefaultvals'] else [] + proallargtypes = data['proallargtypes'] \ + if data['proallargtypes'] else [] + + proargout = [] + proargid = [] + proargmodenames = {'i': 'IN', 'o': 'OUT', 'b': 'INOUT', + 'v': 'VARIADIC', 't': 'TABLE'} + + # The proargtypes doesn't give OUT params, so we need to fetch + # those from database explicitly, below code is written for this + # purpose. + # + # proallargtypes gives all the Function's argument including OUT, + # but we have not used that column; as the data type of this + # column (i.e. oid[]) is not supported by oidvectortypes(oidvector) + # function which we have used to fetch the datatypes + # of the other parameters. + + proargmodes_fltrd = copy.deepcopy(proargmodes) + proargnames_fltrd = [] + cnt = 0 + for m in proargmodes: + if m == 'o': # Out Mode + SQL = render_template("/".join([self.sql_template_path, + 'get_out_types.sql']), + out_arg_oid=proallargtypes[cnt]) + status, out_arg_type = self.conn.execute_scalar(SQL) + if not status: + return internal_server_error(errormsg=out_arg_type) + + # Insert out parameter datatype + proargtypes.insert(cnt, out_arg_type) + proargdefaultvals.insert(cnt, '') + elif m == 'v': # Variadic Mode + proargdefaultvals.insert(cnt, '') + elif m == 't': # Table Mode + proargmodes_fltrd.remove(m) + proargnames_fltrd.append(proargnames[cnt]) + + cnt += 1 + + cnt = 0 + # Map param's short form to its actual name. (ex: 'i' to 'IN') + for m in proargmodes_fltrd: + proargmodes_fltrd[cnt] = proargmodenames[m] + cnt += 1 + + # Removes Argument Names from the list if that argument is removed + # from the list + for i in proargnames_fltrd: + proargnames.remove(i) + + # Insert null value against the parameters which do not have + # default values. + if len(proargmodes_fltrd) > len(proargdefaultvals): + dif = len(proargmodes_fltrd) - len(proargdefaultvals) + while (dif > 0): + proargdefaultvals.insert(0, '') + dif = dif - 1 + + # Prepare list of Argument list dict to be displayed in the Data Grid. + params = {"arguments": [ + self._map_arguments_dict( + i, proargmodes_fltrd[i] if len(proargmodes_fltrd) > i else '', + proargtypes[i] if len(proargtypes) > i else '', + proargnames[i] if len(proargnames) > i else '', + proargdefaultvals[i] if len(proargdefaultvals) > i else '' + ) + for i in range(len(proargtypes))]} + + # Prepare string formatted Argument to be displayed in the Properties + # panel. + + proargs = [self._map_arguments_list( + proargmodes_fltrd[i] if len(proargmodes_fltrd) > i else '', + proargtypes[i] if len(proargtypes) > i else '', + proargnames[i] if len(proargnames) > i else '', + proargdefaultvals[i] if len(proargdefaultvals) > i else '' + ) + for i in range(len(proargtypes))] + + proargs = {"proargs": ", ".join(proargs)} + + return params, proargs + + def _map_arguments_dict(self, argid, argmode, argtype, argname, argdefval): + """ + Returns Dict of formatted Arguments. + Args: + argid: Argument Sequence Number + argmode: Argument Mode + argname: Argument Name + argtype: Argument Type + argdef: Argument Default Value + """ + # The pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) SQL + # statement gives us '-' as a default value for INOUT mode. + # so, replacing it with empty string. + if argmode == 'INOUT' and argdefval.strip() == '-': + argdefval = '' + + return {"argid": argid, + "argtype": argtype.strip() if argtype is not None else '', + "argmode": argmode, + "argname": argname, + "argdefval": argdefval} + + def _map_arguments_list(self, argmode, argtype, argname, argdef): + """ + Returns List of formatted Arguments. + Args: + argmode: Argument Mode + argname: Argument Name + argtype: Argument Type + argdef: Argument Default Value + """ + # The pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) SQL + # statement gives us '-' as a default value for INOUT mode. + # so, replacing it with empty string. + if argmode == 'INOUT' and argdef.strip() == '-': + argdef = '' + + arg = '' + + if argmode and argmode: + arg += argmode + " " + if argname: + arg += argname + " " + if argtype: + arg += argtype + " " + if argdef: + arg += " DEFAULT " + argdef + + return arg.strip(" ") + + def _format_proacl_from_db(self, proacl): + """ + Returns privileges. + Args: + proacl: Privileges Dict + """ + privileges = [] + for row in proacl: + priv = parse_priv_from_db(row) + privileges.append(priv) + + return {"acl": privileges} + + @check_precondition + def types(self, gid, sid, did, scid, fnid=None): + """ + Returns the Data Types. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + fnid: Function Id + """ + + condition = "(typtype IN ('b', 'c', 'd', 'e', 'p', 'r') AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger'))" + if self.blueprint.show_system_objects: + condition += " AND nspname NOT LIKE E'pg\\\\_toast%' AND nspname NOT LIKE E'pg\\\\_temp%'" + + # Get Types + status, types = self.get_types(self.conn, condition) + + if not status: + return internal_server_error(errormsg=types) + + return make_json_response( + data=types, + status=200 + ) + + @check_precondition + def get_languages(self, gid, sid, did, scid, fnid=None): + """ + Returns the Languages list. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + fnid: Function Id + """ + + res = [{'label': '', 'value': ''}] + try: + SQL = render_template("/".join([self.sql_template_path, + 'get_languages.sql']) + ) + status, rows = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res) + + res = res + rows['rows'] + + return make_json_response( + data=res, + status=200 + ) + except: + exc_type, exc_value, exc_traceback = sys.exc_info() + current_app.logger.error(traceback.print_exception( + exc_type, + exc_value, + exc_traceback, + limit=2 + ) + ) + + return internal_server_error(errormsg=str(exc_value)) + + @check_precondition + def variable_options(self, gid, sid, did, scid, fnid=None): + """ + Returns the variables. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + fnid: Function Id + + Returns: + This function will return list of variables available for + table spaces. + """ + SQL = render_template( + "/".join([self.sql_template_path, 'variables.sql']) + ) + status, rset = self.conn.execute_dict(SQL) + + if not status: + return internal_server_error(errormsg=rset) + + return make_json_response( + data=rset['rows'], + status=200 + ) + + @check_precondition + @validate_request + def create(self, gid, sid, did, scid): + """ + Create a new Function object. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + fnid: Function Id + + Returns: + Function object in json format. + """ + + try: + # Get SQL to create Function + status, SQL = self._get_sql(gid, sid, did, scid, self.request) + if not status: + return internal_server_error(errormsg=SQL) + + status, res = self.conn.execute_scalar(SQL) + if not status: + return internal_server_error(errormsg=res) + + SQL = render_template("/".join([self.sql_template_path, + 'get_oid.sql']), + nspname=self.request['pronamespace'], + name=self.request['name']) + status, res = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res) + + res = res['rows'][0] + + return jsonify( + node=self.blueprint.generate_browser_node( + res['oid'], + self.request['pronamespace'], + res['name'], + icon="icon-" + self.node_type, + language=res['lanname'], + funcowner=res['funcowner'] + ) + ) + except Exception as e: + return internal_server_error(errormsg=str(e)) + + @check_precondition + def delete(self, gid, sid, did, scid, fnid): + """ + Drop the Function. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + fnid: Function Id + """ + + if self.cmd == 'delete': + # This is a cascade operation + cascade = True + else: + cascade = False + + try: + # Fetch Name and Schema Name to delete the Function. + SQL = render_template("/".join([self.sql_template_path, + 'delete.sql']), scid=scid, fnid=fnid) + status, res = self.conn.execute_2darray(SQL) + if not status: + return internal_server_error(errormsg=res) + + name, func_args, nspname = res['rows'][0] + + SQL = render_template("/".join([self.sql_template_path, + 'delete.sql']), + name=name, + func_args=func_args, + nspname=nspname, + cascade=cascade) + status, res = self.conn.execute_scalar(SQL) + if not status: + return internal_server_error(errormsg=res) + + return make_json_response( + success=1, + info=gettext("Function Dropped."), + data={ + 'id': fnid, + 'scid': scid, + 'sid': sid, + 'gid': gid, + 'did': did + } + ) + + except Exception as e: + return internal_server_error(errormsg=str(e)) + + @check_precondition + @validate_request + def update(self, gid, sid, did, scid, fnid): + """ + Update the Function. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + fnid: Function Id + """ + + status, SQL = self._get_sql(gid, sid, did, scid, self.request, fnid) + + if not status: + return internal_server_error(errormsg=SQL) + + try: + if SQL and SQL.strip('\n') and SQL.strip(' '): + status, res = self.conn.execute_scalar(SQL) + if not status: + return internal_server_error(errormsg=res) + + return make_json_response( + success=1, + info="Function Updated.", + data={ + 'id': fnid, + 'scid': scid, + 'sid': sid, + 'gid': gid, + 'did': did + } + ) + else: + return make_json_response( + success=1, + info="Nothing to update.", + data={ + 'id': fnid, + 'scid': scid, + 'sid': sid, + 'gid': gid, + 'did': did + } + ) + + except Exception as e: + return internal_server_error(errormsg=str(e)) + + @check_precondition + def sql(self, gid, sid, did, scid, fnid=None): + """ + Returns the SQL for the Function object. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + fnid: Function Id + """ + + if self.node_type == 'procedure': + resp_data = self._fetch_properties(gid, sid, did, scid, fnid) + + # Get SQL to create Function + status, func_def = self._get_sql(gid, sid, did, scid, resp_data, + None, True) + if not status: + return internal_server_error(errormsg=func_def) + + name = resp_data['pronamespace'] + "." + resp_data['name_with_args'] + else: + # Fetch the function definition. + SQL = render_template("/".join([self.sql_template_path, + 'get_definition.sql']), fnid=fnid, scid=scid) + status, res = self.conn.execute_2darray(SQL) + if not status: + return internal_server_error(errormsg=res) + + func_def, name = res['rows'][0] + + sql_header = """-- {0}: {1} + +-- DROP {0} {1}; + +""".format(self.node_type.upper(), name) + + SQL = sql_header + func_def + + return ajax_response(response=SQL) + + @check_precondition + @validate_request + def msql(self, gid, sid, did, scid, fnid=None): + """ + Returns the modified SQL. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + fnid: Function Id + Returns: + SQL statements to create/update the Domain. + """ + + status, SQL = self._get_sql(gid, sid, did, scid, self.request, fnid) + if status: + return make_json_response( + data=SQL, + status=200 + ) + else: + return SQL + + def _get_sql(self, gid, sid, did, scid, data, fnid=None, is_sql=False): + """ + Generates the SQL statements to create/update the Function. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + data: Function data + fnid: Function Id + """ + + try: + vol_dict = {'v': 'VOLATILE', 's': 'STABLE', 'i': 'IMMUTABLE'} + + # Get Schema Name from its OID. + if 'pronamespace' in data: + data['pronamespace'] = self._get_schema(data[ + 'pronamespace']) + if 'provolatile' in data: + data['provolatile'] = vol_dict[data['provolatile']] + + if fnid is not None: + # Edit Mode + + # Fetch Old Data from database. + old_data = self._fetch_properties(gid, sid, did, scid, fnid) + + # Get Schema Name + old_data['pronamespace'] = self._get_schema(old_data[ + 'pronamespace']) + + if 'provolatile' in old_data: + old_data['provolatile'] = vol_dict[old_data['provolatile']] + + # If any of the below argument is changed, + # then CREATE OR REPLACE SQL statement should be called + fun_change_args = ['lanname', 'prosrc', 'probin', 'prosrc_c', + 'provolatile', 'proisstrict', 'prosecdef', + 'procost', 'proleakproof', 'arguments'] + + data['change_func'] = False + for arg in fun_change_args: + if arg == 'arguments' and arg in data and len(data[arg]) \ + > 0: + data['change_func'] = True + elif arg in data: + data['change_func'] = True + + # If Function Definition/Arguments are changed then merge old + # Arguments with changed ones for Create/Replace Function + # SQL statement + if 'arguments' in data and len(data['arguments']) > 0: + for arg in data['arguments']['changed']: + for old_arg in old_data['arguments']: + if arg['argid'] == old_arg['argid']: + old_arg.update(arg) + break + data['arguments'] = old_data['arguments'] + elif data['change_func']: + data['arguments'] = old_data['arguments'] + + # Parse Privileges + if 'acl' in data: + for key in ['added', 'deleted', 'changed']: + if key in data['acl']: + data['acl'][key] = parse_priv_to_db( + data['acl'][key], ["X"]) + + # Parse Variables + chngd_variables = {} + data['merged_variables'] = [] + old_data['chngd_variables'] = {} + del_variables = {} + + # If Function Definition/Arguments are changed then, + # Merge old, new (added, changed, deleted) variables, + # which will be used in the CREATE or REPLACE Function sql + # statement + + if data['change_func']: + # To compare old and new variables, preparing name : + # value dict + + # Deleted Variables + if 'variables' in data and 'deleted' in data['variables']: + for v in data['variables']['deleted']: + del_variables[v['name']] = v['value'] + + if 'variables' in data and 'changed' in data['variables']: + for v in data['variables']['changed']: + chngd_variables[v['name']] = v['value'] + + if 'variables' in data and 'added' in data['variables']: + for v in data['variables']['added']: + chngd_variables[v['name']] = v['value'] + + for v in old_data['variables']: + old_data['chngd_variables'][v['name']] = v['value'] + + # Prepare final dict of new and old variables + for name, val in old_data['chngd_variables'].items(): + if name not in chngd_variables and name not in \ + del_variables: + chngd_variables[name] = val + + # Prepare dict in [{'name': var_name, 'value': var_val},..] + # format + for name, val in chngd_variables.items(): + data['merged_variables'].append({'name': name, + 'value': val}) + else: + if 'variables' in data and 'changed' in data['variables']: + for v in data['variables']['changed']: + data['merged_variables'].append(v) + + if 'variables' in data and 'added' in data['variables']: + for v in data['variables']['added']: + data['merged_variables'].append(v) + + SQL = render_template( + "/".join([self.sql_template_path, 'update.sql']), + data=data, o_data=old_data + ) + else: + # Parse Privileges + if 'acl' in data: + data['acl'] = parse_priv_to_db(data['acl'], ["X"]) + + args = '' + cnt = 1 + if 'arguments' in data: + for a in data['arguments']: + if (('argmode' in a and a['argmode'] != 'OUT' and + a['argmode'] is not None + ) or 'argnode' not in a): + if 'argmode' in a: + args += a['argmode'] + " " + if 'argname' in a and a['argname'] != ''\ + and a['argname'] is not None: + args += self.qtIdent( + self.conn, a['argname']) + " " + if 'argtype' in a: + args += a['argtype'] + if cnt < len(data['arguments']): + args += ', ' + cnt += 1 + + data['func_args'] = args.strip(' ') + # Create mode + SQL = render_template("/".join([self.sql_template_path, + 'create.sql']), + data=data, is_sql=is_sql) + return True, SQL.strip('\n') + + except Exception as e: + return False, e + + def _fetch_properties(self, gid, sid, did, scid, fnid=None): + """ + Return Function Properties which will be used in properties, + msql function. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + fnid: Function Id + """ + + resp_data = {} + + SQL = render_template("/".join([self.sql_template_path, + 'properties.sql']), + scid=scid, fnid=fnid) + status, res = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res) + + if len(res['rows']) == 0: + return gone(gettext(""" +Could not find the function in the database. +It may have been removed by another user or +created/shifted to the another schema. +""")) + + resp_data = res['rows'][0] + + # Get formatted Arguments + frmtd_params, frmtd_proargs = self._format_arguments_from_db(resp_data) + resp_data.update(frmtd_params) + resp_data.update(frmtd_proargs) + + # Fetch privileges + SQL = render_template("/".join([self.sql_template_path, 'acl.sql']), + fnid=fnid) + status, proaclres = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res) + + # Get Formatted Privileges + resp_data.update(self._format_proacl_from_db(proaclres['rows'])) + + # Set System Functions Status + resp_data['sysfunc'] = False + if fnid <= self.manager.db_info[did]['datlastsysoid']: + resp_data['sysfunc'] = True + + # Get formatted Security Labels + if 'seclabels' in resp_data: + resp_data.update(parse_sec_labels_from_db(resp_data['seclabels'])) + + # Get formatted Variable + resp_data.update(parse_variables_from_db([ + {"setconfig": resp_data['proconfig']}])) + + return resp_data + + def _get_schema(self, scid): + """ + Returns Schema Name from its OID. + + Args: + scid: Schema Id + """ + SQL = render_template("/".join([self.sql_template_path, + 'get_schema.sql']), scid=scid) + + status, schema_name = self.conn.execute_scalar(SQL) + + if not status: + return internal_server_error(errormsg=schema_name) + + return schema_name + + @check_precondition + def dependents(self, gid, sid, did, scid, fnid): + """ + This function get the dependents and return ajax response + for the Function node. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + doid: Function Id + """ + dependents_result = self.get_dependents(self.conn, fnid) + return ajax_response( + response=dependents_result, + status=200 + ) + + @check_precondition + def dependencies(self, gid, sid, did, scid, fnid): + """ + This function get the dependencies and return ajax response + for the Function node. + + Args: + gid: Server Group Id + sid: Server Id + did: Database Id + scid: Schema Id + doid: Function Id + """ + dependencies_result = self.get_dependencies(self.conn, fnid) + return ajax_response( + response=dependencies_result, + status=200 + ) + +FunctionView.register_node_view(blueprint) + + +class ProcedureModule(SchemaChildModule): + """ + class ProcedureModule(SchemaChildModule): + + This class represents The Procedures Module. + + Methods: + ------- + * __init__(*args, **kwargs) + - Initialize the Procedures Module. + + * get_nodes(gid, sid, did, scid) + - Generate the Procedures collection node. + + * node_inode(): + - Returns Procedures node as leaf node. + + * script_load() + - Load the module script for Procedures, when schema node is + initialized. + + """ + + NODE_TYPE = 'procedure' + COLLECTION_LABEL = gettext("Procedures") + + def __init__(self, *args, **kwargs): + """ + Initialize the Procedure Module. + Args: + *args: + **kwargs: + """ + super(ProcedureModule, self).__init__(*args, **kwargs) + + self.min_ver = 90100 + self.max_ver = None + self.server_type = ['ppas'] + + def get_nodes(self, gid, sid, did, scid): + """ + Generate Procedures collection node. + """ + yield self.generate_browser_collection_node(scid) + + @property + def node_inode(self): + """ + Make the node as leaf node. + Returns: + False as this node doesn't have child nodes. + """ + return False + + @property + def script_load(self): + """ + Load the module script for Procedures, when the + schema node is initialized. + """ + return schemas.SchemaModule.NODE_TYPE + + +procedure_blueprint = ProcedureModule(__name__) + + +class ProcedureView(FunctionView): + + node_type = procedure_blueprint.node_type + + def __init__(self, *args, **kwargs): + """ + Initialize the Function Module. + Args: + *args: + **kwargs: + """ + super(ProcedureView, self).__init__(*args, **kwargs) + + @property + def required_args(self): + """ + Returns Required arguments for procedures node. + Where + Required Args: + name: Name of the Function + pronamespace: Function Namespace + lanname: Function Language Name + prosrc: Function Code + """ + return ['name', + 'pronamespace', + 'lanname', + 'prosrc'] + + def module_js(self): + """ + Load JS file (procedures.js) for this module. + """ + + return make_response( + render_template( + "procedure/js/procedures.js", + _=gettext + ), + 200, {'Content-Type': 'application/x-javascript'} + ) + +ProcedureView.register_node_view(procedure_blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/coll-function.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/coll-function.png new file mode 100644 index 0000000000000000000000000000000000000000..c44874e5574e624c2687689ac75f3ba4ed69e811 GIT binary patch literal 349 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!aez;VE0CVL=8;#?*`-(h^sRi9 z*>&~c)34PF?}pc0oO}FT&eYpg3!lCJ{{QpuKPl}Gawb0N+VtXry&)e^8)He3UoeBi zvm0qZ4rhT!WHFHT0Ash4*>*riqNj^vh{WaCes{hD1{^FOt?qvPzrI(~vFzEgEEaCT zKn8&fCc|T@oHyDw|30!InX~Vp=DDQ@|E}SiWNDf1d5o{vOS9^Kd7b7@Arcm|Gc`Y8#kY85l5Do_~mzopr06KSqcmMzZ literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/coll-procedure.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/coll-procedure.png new file mode 100644 index 0000000000000000000000000000000000000000..7c13a9bc73a782b5139095af596e15d7b68dd20c GIT binary patch literal 337 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFv5AX?b1=9EC%sCbm^nUN&dsC)d z%g%m(?%cJOmUB^2&)2TKR$To5`}b?r)x6ex&wxr9OM?7@862M7NCR>>3p^r=fwTu0 zyPeFo12PglT^vI=t|uoXgaoB9FsmgiGa57px_XMbaBFHxO0zOZW@WzA@{)3Bd#1Ev zf>nS=wRyl)0gsIDYK$8M1T>mj(wGjaEU!C8<`)MX5lF!N|bSP}jgv*T^))(A3Jn+{)NY+rZ4q zz+j);rTHita`RI%(<(t440H`FfqFuWjIB&etPFq}fI1CMO%GiI)WG2B>gTe~DWM4f DC&Fq! literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/function.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/function.png new file mode 100644 index 0000000000000000000000000000000000000000..656854a0191b5dd5d465f90cfbceebdc3913f1a2 GIT binary patch literal 325 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPHF3h)VW1=3U3Jn||!yY$MRhadm{ z{r~UY=bu~de4cgqZS9ih={*lqIv$kGe$v0=Wy+ox+kmPWOM?7@862M7NCR>>3p^r= zfwTu0yPeFo12Td!SQ6wH%;50sMjDXAS>O>_45U54 z*zIJt9gq>^>Eal|aXmS~fyt>$U{>Hw4~8=dMTLzVhO64x7+WQ#PMLD)QiGGvQ-uJP z0|%}!vT^bF7&|6RVu(1qDl{Rt=hklXM&2Z=Vz#WlMH3iS#bz)t#6K1K?su -1) + return true; + + if ('coll-function' == d._type) { + //Check if we are not child of catalog + prev_i = t.hasParent(i) ? t.parent(i) : null; + prev_d = prev_i ? t.itemData(prev_i) : null; + if( prev_d._type == 'catalog') { + return false; + } else { + return true; + } + } + i = t.hasParent(i) ? t.parent(i) : null; + d = i ? t.itemData(i) : null; + } + // by default we do not want to allow create menu + return true; + } + }); + + } + + return pgBrowser.Nodes['function']; +}); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/acl.sql new file mode 100644 index 000000000..ad3e0d156 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/acl.sql @@ -0,0 +1,35 @@ +SELECT + COALESCE(gt.rolname, 'public') AS grantee, + g.rolname AS grantor, array_agg(privilege_type) AS privileges, + array_agg(is_grantable) AS grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT + (d).grantee AS grantee, (d).grantor AS grantor, + (d).is_grantable AS is_grantable, + (d).privilege_type AS privilege_type + FROM + (SELECT aclexplode(db.proacl) AS d FROM pg_proc db + WHERE db.oid = {{fnid}}::OID) a + ) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/create.sql new file mode 100644 index 000000000..7b29a3c6d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/create.sql @@ -0,0 +1,53 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %} +{% set is_columns = [] %} +{% if data %} +CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %},{% endif %} +{% endfor %} +{% endif -%} + ) + RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }} + LANGUAGE {{ data.lanname|qtLiteral }} + {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proisstrict %}STRICT {% endif %}{% if data.prosecdef %}SECURITY DEFINER {% endif %}{% if data.proiswindow %}WINDOW{% endif -%}{% if data.procost %} + + COST {{data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %} +{% endif %} + +AS {% if data.lanname == 'c' %} +{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }} +{% else %} +$function$ +{{ data.prosrc }} +$function${% endif %}; +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + OWNER TO {{ data.funcowner }}; +{% endif %} +{% if data.acl %} +{% for p in data.acl %} + +{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}} +{% endfor %}{% endif %} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + IS '{{ data.description }}'; +{% endif -%} +{% if data.seclabels %} +{% for r in data.seclabels %} +{% if r.security_label and r.provider %} + +{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }} +{% endif %} +{% endfor %} +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/delete.sql new file mode 100644 index 000000000..246bec12d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/delete.sql @@ -0,0 +1,21 @@ +{% if scid and fnid %} +SELECT + pr.proname as name, '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args, + nspname +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.oid = {{fnid}}; +{% endif %} + +{% if name %} +DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_definition.sql new file mode 100644 index 000000000..589eccee6 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_definition.sql @@ -0,0 +1,11 @@ +SELECT + pg_get_functiondef({{fnid}}::oid) AS func_def, + nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name +FROM + pg_proc pr +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND pr.oid = {{fnid}}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_languages.sql new file mode 100644 index 000000000..f81ddfbda --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_languages.sql @@ -0,0 +1,4 @@ +SELECT + lanname as label, lanname as value +FROM + pg_language; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_oid.sql new file mode 100644 index 000000000..2bc76a2e4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_oid.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace + AND nsp.nspname={{ nspname|qtLiteral }} +WHERE + proisagg = FALSE + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.proname = {{ name|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_out_types.sql new file mode 100644 index 000000000..64a11875f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_out_types.sql @@ -0,0 +1,6 @@ +SELECT + format_type(oid, NULL) AS out_arg_type +FROM + pg_type +WHERE + oid = {{ out_arg_oid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_schema.sql new file mode 100644 index 000000000..127d4b9db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_schema.sql @@ -0,0 +1,6 @@ +SELECT + nspname +FROM + pg_namespace +WHERE + oid = {{ scid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_types.sql new file mode 100644 index 000000000..2a5582ee9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_types.sql @@ -0,0 +1,20 @@ +SELECT + * +FROM + (SELECT + format_type(t.oid,NULL) AS typname, + CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname, + (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup + FROM + pg_type t + JOIN + pg_namespace nsp ON typnamespace=nsp.oid + WHERE + (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) + AND + ( + typtype IN ('b', 'c', 'd', 'e', 'p', 'r') + AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger') + ) + ) AS dummy +ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/node.sql new file mode 100644 index 000000000..bb6ec9dc8 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/node.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner, description +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/properties.sql new file mode 100644 index 000000000..9e8a8baaa --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/properties.sql @@ -0,0 +1,31 @@ +SELECT + pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c, + pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename, + typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames, + pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, + pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description, + (SELECT + array_agg(provider || '=' || label) + FROM + pg_seclabel sl1 + WHERE + sl1.objoid=pr.oid) AS seclabels +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace typns ON typns.oid=typ.typnamespace +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +{% if fnid %} + AND pr.oid = {{fnid}}::oid +{% endif %} +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/update.sql new file mode 100644 index 000000000..6b0128a10 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/update.sql @@ -0,0 +1,105 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %} +{% set name = o_data.name %} +{% if data.name %} +{% if data.name != o_data.name %} +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }}) + RENAME TO {{ conn|qtIdent(data.name) }}; +{% set name = data.name %} +{% endif %} +{% endif -%} +{% if data.change_func %} + +CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %}, {% endif %} +{% endfor %} +{% endif -%} +) + RETURNS {{ o_data.prorettypename }} +{% if 'lanname' in data %} + LANGUAGE {{ data.lanname|qtLiteral }} {% else %} + LANGUAGE {{ o_data.lanname|qtLiteral }} + {% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %} +{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %} +{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} +{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} + + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%} + {% endif %} + +AS {% if 'probin' in data or 'prosrc_c' in data %} +{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} +$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %} +{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} +$function${{ o_data.prosrc }}$function${% endif -%}; +{% endif -%} +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }}) + OWNER TO {{ data.funcowner }}; +{% endif -%} +{# The SQL generated below will change priviledges #} +{% if data.acl %} +{% if 'deleted' in data.acl %} +{% for priv in data.acl.deleted %} +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{% endfor %}{% endif %} +{% if 'changed' in data.acl %} +{% for priv in data.acl.changed %} +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} + +{% endfor %}{% endif %} +{% if 'added' in data.acl %} +{% for priv in data.acl.added %} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %}{% endif %}{% endif %} +{% if data.change_func == False %} +{% if data.variables %} +{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %} + +{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames ) }} +{% endif -%} +{% if 'merged_variables' in data and data.merged_variables|length > 0 %} + +{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames ) }} +{% endif %} +{% endif %}{% endif %} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} +{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }} + +{% endfor %} +{% endif -%} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} + +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %}{% endif -%} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }}) + IS {{ data.description|qtLiteral }}; +{% endif -%} +{% if data.pronamespace %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }}) + SET SCHEMA {{ conn|qtIdent(data.pronamespace) }}; +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/variables.sql new file mode 100644 index 000000000..5233c71ec --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/variables.sql @@ -0,0 +1,6 @@ +SELECT + name, vartype, min_val, max_val, enumvals +FROM + pg_settings +WHERE + context in ('user', 'superuser'); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/acl.sql new file mode 100644 index 000000000..ad3e0d156 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/acl.sql @@ -0,0 +1,35 @@ +SELECT + COALESCE(gt.rolname, 'public') AS grantee, + g.rolname AS grantor, array_agg(privilege_type) AS privileges, + array_agg(is_grantable) AS grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT + (d).grantee AS grantee, (d).grantor AS grantor, + (d).is_grantable AS is_grantable, + (d).privilege_type AS privilege_type + FROM + (SELECT aclexplode(db.proacl) AS d FROM pg_proc db + WHERE db.oid = {{fnid}}::OID) a + ) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/create.sql new file mode 100644 index 000000000..50de6dc10 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/create.sql @@ -0,0 +1,57 @@ +{% import 'macros/functions/security.macros' as SECLABLE %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %} +{% set is_columns = [] %} +{% if data %} +CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %},{% endif %} +{% endfor %} +{% endif -%} + ) + RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }} + LANGUAGE {{ data.lanname|qtLiteral }} + {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %}LEAKPROOF {% else %}NOT LEAKPROOF {% endif %} +{% if data.proisstrict %}STRICT {% endif %} +{% if data.prosecdef %}SECURITY DEFINER {% endif %} +{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %} + + COST {{data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %} +{% endif %} + +AS {% if data.lanname == 'c' %} +{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }} +{% else %} +$function$ +{{ data.prosrc }} +$function${% endif -%}; +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + OWNER TO {{ data.funcowner }}; +{% endif -%} +{% if data.acl %} +{% for p in data.acl %} + +{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}} +{% endfor -%} +{% endif -%} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + IS '{{ data.description }}'; +{% endif -%} +{% if data.seclabels %} +{% for r in data.seclabels %} +{% if r.security_label and r.provider %} + +{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }} +{% endif %} +{% endfor %} +{% endif -%} + +{% endif -%} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/delete.sql new file mode 100644 index 000000000..246bec12d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/delete.sql @@ -0,0 +1,21 @@ +{% if scid and fnid %} +SELECT + pr.proname as name, '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args, + nspname +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.oid = {{fnid}}; +{% endif %} + +{% if name %} +DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_definition.sql new file mode 100644 index 000000000..589eccee6 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_definition.sql @@ -0,0 +1,11 @@ +SELECT + pg_get_functiondef({{fnid}}::oid) AS func_def, + nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name +FROM + pg_proc pr +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND pr.oid = {{fnid}}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_languages.sql new file mode 100644 index 000000000..f81ddfbda --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_languages.sql @@ -0,0 +1,4 @@ +SELECT + lanname as label, lanname as value +FROM + pg_language; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_oid.sql new file mode 100644 index 000000000..2bc76a2e4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_oid.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace + AND nsp.nspname={{ nspname|qtLiteral }} +WHERE + proisagg = FALSE + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.proname = {{ name|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_out_types.sql new file mode 100644 index 000000000..64a11875f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_out_types.sql @@ -0,0 +1,6 @@ +SELECT + format_type(oid, NULL) AS out_arg_type +FROM + pg_type +WHERE + oid = {{ out_arg_oid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_schema.sql new file mode 100644 index 000000000..127d4b9db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_schema.sql @@ -0,0 +1,6 @@ +SELECT + nspname +FROM + pg_namespace +WHERE + oid = {{ scid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_types.sql new file mode 100644 index 000000000..2a5582ee9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_types.sql @@ -0,0 +1,20 @@ +SELECT + * +FROM + (SELECT + format_type(t.oid,NULL) AS typname, + CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname, + (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup + FROM + pg_type t + JOIN + pg_namespace nsp ON typnamespace=nsp.oid + WHERE + (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) + AND + ( + typtype IN ('b', 'c', 'd', 'e', 'p', 'r') + AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger') + ) + ) AS dummy +ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/node.sql new file mode 100644 index 000000000..bb6ec9dc8 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/node.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner, description +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/properties.sql new file mode 100644 index 000000000..ff7829808 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/properties.sql @@ -0,0 +1,31 @@ +SELECT + pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c, + pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename, + typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames, + pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, + pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description, + (SELECT + array_agg(provider || '=' || label) + FROM + pg_shseclabel sl1 + WHERE + sl1.objoid=pr.oid) AS seclabels +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace typns ON typns.oid=typ.typnamespace +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +{% if fnid %} + AND pr.oid = {{fnid}}::oid +{% endif %} +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/update.sql new file mode 100644 index 000000000..2b47dcd2e --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/update.sql @@ -0,0 +1,114 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %} +{% set name = o_data.name %} +{% if data.name %} +{% if data.name != o_data.name %} +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }}) + RENAME TO {{ conn|qtIdent(data.name) }}; +{% set name = data.name %} +{% endif %} +{% endif -%} +{% if data.change_func %} + +CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %}, {% endif %} +{% endfor %} +{% endif -%} +) + RETURNS {{ o_data.prorettypename }} +{% if 'lanname' in data %} + LANGUAGE {{ data.lanname|qtLiteral }} {% else %} + LANGUAGE {{ o_data.lanname|qtLiteral }} + {% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %} +{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %}LEAKPROOF{% elif 'proleakproof' in data and not data.proleakproof %}NOT LEAKPROOF{% endif %} +{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %} +{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} +{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} + + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%} + {% endif %} + +AS {% if 'probin' in data or 'prosrc_c' in data %} +{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} +$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %} +{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} +$function${{ o_data.prosrc }}$function${% endif -%}; +{% endif -%} + +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }}) + OWNER TO {{ data.funcowner }}; +{% endif -%} +{# The SQL generated below will change priviledges #} +{% if data.acl %} +{% if 'deleted' in data.acl %} +{% for priv in data.acl.deleted %} + +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in data.acl %} +{% for priv in data.acl.changed %} + +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in data.acl %} +{% for priv in data.acl.added %} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif %} +{% endif -%} +{% if data.change_func == False %} +{% if data.variables %} +{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %} + +{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames ) }} +{% endif -%} +{% if 'merged_variables' in data and data.merged_variables|length > 0 %} + +{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames ) }} +{% endif -%} +{% endif -%} +{% endif -%} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} + +{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} + +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} + +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }}) + IS {{ data.description|qtLiteral }}; +{% endif -%} +{% if data.pronamespace %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }}) + SET SCHEMA {{ conn|qtIdent(data.pronamespace) }}; +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/variables.sql new file mode 100644 index 000000000..5233c71ec --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/variables.sql @@ -0,0 +1,6 @@ +SELECT + name, vartype, min_val, max_val, enumvals +FROM + pg_settings +WHERE + context in ('user', 'superuser'); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/acl.sql new file mode 100644 index 000000000..ad3e0d156 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/acl.sql @@ -0,0 +1,35 @@ +SELECT + COALESCE(gt.rolname, 'public') AS grantee, + g.rolname AS grantor, array_agg(privilege_type) AS privileges, + array_agg(is_grantable) AS grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT + (d).grantee AS grantee, (d).grantor AS grantor, + (d).is_grantable AS is_grantable, + (d).privilege_type AS privilege_type + FROM + (SELECT aclexplode(db.proacl) AS d FROM pg_proc db + WHERE db.oid = {{fnid}}::OID) a + ) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/create.sql new file mode 100644 index 000000000..48a7a843a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/create.sql @@ -0,0 +1,57 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %} +{% set is_columns = [] %} +{% if data %} +CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data +.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}}{% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %},{% endif %} +{% endfor %} +{% endif -%} + ) + RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }} + LANGUAGE {{ data.lanname|qtLiteral }} + {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %}LEAKPROOF {% else %}NOT LEAKPROOF {% endif %} +{% if data.proisstrict %}STRICT {% endif %} +{% if data.prosecdef %}SECURITY DEFINER {% endif %} +{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %} + + COST {{data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %} +{% endif %} + +AS {% if data.lanname == 'c' %} +{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }} +{% else %} +$function$ +{{ data.prosrc }} +$function${% endif -%}; +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + OWNER TO {{ data.funcowner }}; +{% endif -%} +{% if data.acl %} +{% for p in data.acl %} + +{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}} +{% endfor %}{% endif %} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + IS '{{ data.description }}'; +{% endif -%} +{% if data.seclabels %} +{% for r in data.seclabels %} +{% if r.security_label and r.provider %} + +{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }} +{% endif %} +{% endfor %} +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/delete.sql new file mode 100644 index 000000000..246bec12d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/delete.sql @@ -0,0 +1,21 @@ +{% if scid and fnid %} +SELECT + pr.proname as name, '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args, + nspname +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.oid = {{fnid}}; +{% endif %} + +{% if name %} +DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_definition.sql new file mode 100644 index 000000000..589eccee6 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_definition.sql @@ -0,0 +1,11 @@ +SELECT + pg_get_functiondef({{fnid}}::oid) AS func_def, + nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name +FROM + pg_proc pr +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND pr.oid = {{fnid}}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_languages.sql new file mode 100644 index 000000000..f81ddfbda --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_languages.sql @@ -0,0 +1,4 @@ +SELECT + lanname as label, lanname as value +FROM + pg_language; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_oid.sql new file mode 100644 index 000000000..2bc76a2e4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_oid.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace + AND nsp.nspname={{ nspname|qtLiteral }} +WHERE + proisagg = FALSE + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.proname = {{ name|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_out_types.sql new file mode 100644 index 000000000..64a11875f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_out_types.sql @@ -0,0 +1,6 @@ +SELECT + format_type(oid, NULL) AS out_arg_type +FROM + pg_type +WHERE + oid = {{ out_arg_oid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_schema.sql new file mode 100644 index 000000000..127d4b9db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_schema.sql @@ -0,0 +1,6 @@ +SELECT + nspname +FROM + pg_namespace +WHERE + oid = {{ scid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_types.sql new file mode 100644 index 000000000..2a5582ee9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_types.sql @@ -0,0 +1,20 @@ +SELECT + * +FROM + (SELECT + format_type(t.oid,NULL) AS typname, + CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname, + (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup + FROM + pg_type t + JOIN + pg_namespace nsp ON typnamespace=nsp.oid + WHERE + (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) + AND + ( + typtype IN ('b', 'c', 'd', 'e', 'p', 'r') + AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger') + ) + ) AS dummy +ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/node.sql new file mode 100644 index 000000000..bb6ec9dc8 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/node.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner, description +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/properties.sql new file mode 100644 index 000000000..ff7829808 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/properties.sql @@ -0,0 +1,31 @@ +SELECT + pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c, + pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename, + typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames, + pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, + pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description, + (SELECT + array_agg(provider || '=' || label) + FROM + pg_shseclabel sl1 + WHERE + sl1.objoid=pr.oid) AS seclabels +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace typns ON typns.oid=typ.typnamespace +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +{% if fnid %} + AND pr.oid = {{fnid}}::oid +{% endif %} +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/update.sql new file mode 100644 index 000000000..1d920fc2c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/update.sql @@ -0,0 +1,114 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %} +{% set name = o_data.name %} +{% if data.name %} +{% if data.name != o_data.name %} +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{ +o_data.proargtypenames }}) + RENAME TO {{ conn|qtIdent(data.name) }}; +{% set name = data.name %} +{% endif %} +{% endif -%} +{% if data.change_func %} + +CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %},{% endif %} +{% endfor %} +{% endif -%} +) + RETURNS {{ o_data.prorettypename }} +{% if 'lanname' in data %} + LANGUAGE {{ data.lanname|qtLiteral }} {% else %} + LANGUAGE {{ o_data.lanname|qtLiteral }} + {% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %} +{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %}LEAKPROOF{% elif 'proleakproof' in data and not data.proleakproof %}NOT LEAKPROOF{% endif %} +{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %} +{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} +{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} + + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%} + {% endif %} + +AS {% if 'probin' in data or 'prosrc_c' in data %} +{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} +$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %} +{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} +$function${{ o_data.prosrc }}$function${% endif -%}; +{% endif -%} +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }}) + OWNER TO {{ data.funcowner }}; +{% endif -%} +{# The SQL generated below will change priviledges #} +{% if data.acl %} +{% if 'deleted' in data.acl %} +{% for priv in data.acl.deleted %} + +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in data.datacl %} +{% for priv in data.acl.changed %} + +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in data.acl %} +{% for priv in data.acl.added %} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %}{% endif -%} +{% endif -%} +{% if data.change_func == False %} +{% if data.variables %} +{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %} + +{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }} +{% endif -%} +{% if 'merged_variables' in data and data.merged_variables|length > 0 %} + +{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }} +{% endif -%} +{% endif -%} +{% endif -%} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} + +{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} + +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} + +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }}) + IS {{ data.description|qtLiteral }}; +{% endif -%} + +{% if data.pronamespace %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }}) + SET SCHEMA {{ conn|qtIdent(data.pronamespace) }}; +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/variables.sql new file mode 100644 index 000000000..5233c71ec --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/variables.sql @@ -0,0 +1,6 @@ +SELECT + name, vartype, min_val, max_val, enumvals +FROM + pg_settings +WHERE + context in ('user', 'superuser'); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/acl.sql new file mode 100644 index 000000000..ad3e0d156 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/acl.sql @@ -0,0 +1,35 @@ +SELECT + COALESCE(gt.rolname, 'public') AS grantee, + g.rolname AS grantor, array_agg(privilege_type) AS privileges, + array_agg(is_grantable) AS grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT + (d).grantee AS grantee, (d).grantor AS grantor, + (d).is_grantable AS is_grantable, + (d).privilege_type AS privilege_type + FROM + (SELECT aclexplode(db.proacl) AS d FROM pg_proc db + WHERE db.oid = {{fnid}}::OID) a + ) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/create.sql new file mode 100644 index 000000000..7b29a3c6d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/create.sql @@ -0,0 +1,53 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %} +{% set is_columns = [] %} +{% if data %} +CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %},{% endif %} +{% endfor %} +{% endif -%} + ) + RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }} + LANGUAGE {{ data.lanname|qtLiteral }} + {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proisstrict %}STRICT {% endif %}{% if data.prosecdef %}SECURITY DEFINER {% endif %}{% if data.proiswindow %}WINDOW{% endif -%}{% if data.procost %} + + COST {{data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %} +{% endif %} + +AS {% if data.lanname == 'c' %} +{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }} +{% else %} +$function$ +{{ data.prosrc }} +$function${% endif %}; +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + OWNER TO {{ data.funcowner }}; +{% endif %} +{% if data.acl %} +{% for p in data.acl %} + +{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}} +{% endfor %}{% endif %} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + IS '{{ data.description }}'; +{% endif -%} +{% if data.seclabels %} +{% for r in data.seclabels %} +{% if r.security_label and r.provider %} + +{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }} +{% endif %} +{% endfor %} +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/delete.sql new file mode 100644 index 000000000..246bec12d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/delete.sql @@ -0,0 +1,21 @@ +{% if scid and fnid %} +SELECT + pr.proname as name, '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args, + nspname +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.oid = {{fnid}}; +{% endif %} + +{% if name %} +DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_definition.sql new file mode 100644 index 000000000..589eccee6 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_definition.sql @@ -0,0 +1,11 @@ +SELECT + pg_get_functiondef({{fnid}}::oid) AS func_def, + nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name +FROM + pg_proc pr +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND pr.oid = {{fnid}}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_languages.sql new file mode 100644 index 000000000..f81ddfbda --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_languages.sql @@ -0,0 +1,4 @@ +SELECT + lanname as label, lanname as value +FROM + pg_language; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_oid.sql new file mode 100644 index 000000000..2bc76a2e4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_oid.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace + AND nsp.nspname={{ nspname|qtLiteral }} +WHERE + proisagg = FALSE + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.proname = {{ name|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_out_types.sql new file mode 100644 index 000000000..64a11875f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_out_types.sql @@ -0,0 +1,6 @@ +SELECT + format_type(oid, NULL) AS out_arg_type +FROM + pg_type +WHERE + oid = {{ out_arg_oid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_schema.sql new file mode 100644 index 000000000..127d4b9db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_schema.sql @@ -0,0 +1,6 @@ +SELECT + nspname +FROM + pg_namespace +WHERE + oid = {{ scid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_types.sql new file mode 100644 index 000000000..2a5582ee9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_types.sql @@ -0,0 +1,20 @@ +SELECT + * +FROM + (SELECT + format_type(t.oid,NULL) AS typname, + CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname, + (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup + FROM + pg_type t + JOIN + pg_namespace nsp ON typnamespace=nsp.oid + WHERE + (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) + AND + ( + typtype IN ('b', 'c', 'd', 'e', 'p', 'r') + AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger') + ) + ) AS dummy +ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/node.sql new file mode 100644 index 000000000..c7f41596d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/node.sql @@ -0,0 +1,18 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' AS name, + lanname, pg_get_userbyid(proowner) AS funcowner, description +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pr.protype = '0'::char + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/properties.sql new file mode 100644 index 000000000..9e8a8baaa --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/properties.sql @@ -0,0 +1,31 @@ +SELECT + pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c, + pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename, + typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames, + pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, + pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description, + (SELECT + array_agg(provider || '=' || label) + FROM + pg_seclabel sl1 + WHERE + sl1.objoid=pr.oid) AS seclabels +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace typns ON typns.oid=typ.typnamespace +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +{% if fnid %} + AND pr.oid = {{fnid}}::oid +{% endif %} +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/update.sql new file mode 100644 index 000000000..6b0128a10 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/update.sql @@ -0,0 +1,105 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %} +{% set name = o_data.name %} +{% if data.name %} +{% if data.name != o_data.name %} +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }}) + RENAME TO {{ conn|qtIdent(data.name) }}; +{% set name = data.name %} +{% endif %} +{% endif -%} +{% if data.change_func %} + +CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %}, {% endif %} +{% endfor %} +{% endif -%} +) + RETURNS {{ o_data.prorettypename }} +{% if 'lanname' in data %} + LANGUAGE {{ data.lanname|qtLiteral }} {% else %} + LANGUAGE {{ o_data.lanname|qtLiteral }} + {% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %} +{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %} +{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} +{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} + + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%} + {% endif %} + +AS {% if 'probin' in data or 'prosrc_c' in data %} +{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} +$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %} +{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} +$function${{ o_data.prosrc }}$function${% endif -%}; +{% endif -%} +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }}) + OWNER TO {{ data.funcowner }}; +{% endif -%} +{# The SQL generated below will change priviledges #} +{% if data.acl %} +{% if 'deleted' in data.acl %} +{% for priv in data.acl.deleted %} +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{% endfor %}{% endif %} +{% if 'changed' in data.acl %} +{% for priv in data.acl.changed %} +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} + +{% endfor %}{% endif %} +{% if 'added' in data.acl %} +{% for priv in data.acl.added %} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %}{% endif %}{% endif %} +{% if data.change_func == False %} +{% if data.variables %} +{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %} + +{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames ) }} +{% endif -%} +{% if 'merged_variables' in data and data.merged_variables|length > 0 %} + +{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames ) }} +{% endif %} +{% endif %}{% endif %} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} +{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }} + +{% endfor %} +{% endif -%} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} + +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %}{% endif -%} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }}) + IS {{ data.description|qtLiteral }}; +{% endif -%} +{% if data.pronamespace %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }}) + SET SCHEMA {{ conn|qtIdent(data.pronamespace) }}; +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/variables.sql new file mode 100644 index 000000000..5233c71ec --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/variables.sql @@ -0,0 +1,6 @@ +SELECT + name, vartype, min_val, max_val, enumvals +FROM + pg_settings +WHERE + context in ('user', 'superuser'); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/acl.sql new file mode 100644 index 000000000..ad3e0d156 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/acl.sql @@ -0,0 +1,35 @@ +SELECT + COALESCE(gt.rolname, 'public') AS grantee, + g.rolname AS grantor, array_agg(privilege_type) AS privileges, + array_agg(is_grantable) AS grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT + (d).grantee AS grantee, (d).grantor AS grantor, + (d).is_grantable AS is_grantable, + (d).privilege_type AS privilege_type + FROM + (SELECT aclexplode(db.proacl) AS d FROM pg_proc db + WHERE db.oid = {{fnid}}::OID) a + ) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/create.sql new file mode 100644 index 000000000..70a3d4333 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/create.sql @@ -0,0 +1,57 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %} +{% set is_columns = [] %} +{% if data %} +CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %},{% endif %} +{% endfor %} +{% endif -%} + ) + RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }} + LANGUAGE {{ data.lanname|qtLiteral }} + {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %} LEAKPROOF {% else %} NOT LEAKPROOF {% endif %} +{% if data.proisstrict %}STRICT {% endif %} +{% if data.prosecdef %}SECURITY DEFINER {% endif %} +{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %} + + COST {{data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %} +{% endif %} + +AS {% if data.lanname == 'c' %} +{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }} +{% else %} +$function$ +{{ data.prosrc }} +$function${% endif -%}; +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + OWNER TO {{ data.funcowner }}; +{% endif -%} +{% if data.acl %} +{% for p in data.acl %} + +{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}} +{% endfor -%} +{% endif -%} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + IS '{{ data.description }}'; +{% endif -%} +{% if data.seclabels %} +{% for r in data.seclabels %} +{% if r.security_label and r.provider %} + +{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }} +{% endif %} +{% endfor %} +{% endif -%} + +{% endif -%} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/delete.sql new file mode 100644 index 000000000..c24970c69 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/delete.sql @@ -0,0 +1,22 @@ +{% if scid and fnid %} +SELECT + pr.proname as name, '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args, + nspname +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.oid = {{fnid}}; +{% endif %} + +{% if name %} +DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade%} CASCADE{% +endif %}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_definition.sql new file mode 100644 index 000000000..589eccee6 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_definition.sql @@ -0,0 +1,11 @@ +SELECT + pg_get_functiondef({{fnid}}::oid) AS func_def, + nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name +FROM + pg_proc pr +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND pr.oid = {{fnid}}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_languages.sql new file mode 100644 index 000000000..f81ddfbda --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_languages.sql @@ -0,0 +1,4 @@ +SELECT + lanname as label, lanname as value +FROM + pg_language; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_oid.sql new file mode 100644 index 000000000..2bc76a2e4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_oid.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace + AND nsp.nspname={{ nspname|qtLiteral }} +WHERE + proisagg = FALSE + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.proname = {{ name|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_out_types.sql new file mode 100644 index 000000000..64a11875f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_out_types.sql @@ -0,0 +1,6 @@ +SELECT + format_type(oid, NULL) AS out_arg_type +FROM + pg_type +WHERE + oid = {{ out_arg_oid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_schema.sql new file mode 100644 index 000000000..127d4b9db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_schema.sql @@ -0,0 +1,6 @@ +SELECT + nspname +FROM + pg_namespace +WHERE + oid = {{ scid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_types.sql new file mode 100644 index 000000000..2a5582ee9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_types.sql @@ -0,0 +1,20 @@ +SELECT + * +FROM + (SELECT + format_type(t.oid,NULL) AS typname, + CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname, + (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup + FROM + pg_type t + JOIN + pg_namespace nsp ON typnamespace=nsp.oid + WHERE + (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) + AND + ( + typtype IN ('b', 'c', 'd', 'e', 'p', 'r') + AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger') + ) + ) AS dummy +ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/node.sql new file mode 100644 index 000000000..c7f41596d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/node.sql @@ -0,0 +1,18 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' AS name, + lanname, pg_get_userbyid(proowner) AS funcowner, description +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pr.protype = '0'::char + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/properties.sql new file mode 100644 index 000000000..ff7829808 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/properties.sql @@ -0,0 +1,31 @@ +SELECT + pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c, + pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename, + typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames, + pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, + pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description, + (SELECT + array_agg(provider || '=' || label) + FROM + pg_shseclabel sl1 + WHERE + sl1.objoid=pr.oid) AS seclabels +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace typns ON typns.oid=typ.typnamespace +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +{% if fnid %} + AND pr.oid = {{fnid}}::oid +{% endif %} +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/update.sql new file mode 100644 index 000000000..edf13ec80 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/update.sql @@ -0,0 +1,114 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %} +{% set name = o_data.name %} +{% if data.name %} +{% if data.name != o_data.name %} +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }}) + RENAME TO {{ conn|qtIdent(data.name) }}; +{% set name = data.name %} +{% endif %} +{% endif -%} +{% if data.change_func %} + +CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %}, {% endif %} +{% endfor %} +{% endif -%} +) + RETURNS {{ o_data.prorettypename }} +{% if 'lanname' in data %} + LANGUAGE {{ data.lanname|qtLiteral }} {% else %} + LANGUAGE {{ o_data.lanname|qtLiteral }} + {% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %} +{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %} LEAKPROOF{% elif 'proleakproof' in data and not data.proleakproof %} NOT LEAKPROOF{% endif %} +{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %} +{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} +{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} + + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%} + {% endif %} + +AS {% if 'probin' in data or 'prosrc_c' in data %} +{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} +$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %} +{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} +$function${{ o_data.prosrc }}$function${% endif -%}; +{% endif -%} + +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }}) + OWNER TO {{ data.funcowner }}; +{% endif -%} +{# The SQL generated below will change priviledges #} +{% if data.acl %} +{% if 'deleted' in data.acl %} +{% for priv in data.acl.deleted %} + +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in data.acl %} +{% for priv in data.acl.changed %} + +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in data.acl %} +{% for priv in data.acl.added %} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif %} +{% endif -%} +{% if data.change_func == False %} +{% if data.variables %} +{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %} + +{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames ) }} +{% endif -%} +{% if 'merged_variables' in data and data.merged_variables|length > 0 %} + +{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames ) }} +{% endif -%} +{% endif -%} +{% endif -%} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} + +{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} + +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} + +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }}) + IS {{ data.description|qtLiteral }}; +{% endif -%} +{% if data.pronamespace %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }}) + SET SCHEMA {{ conn|qtIdent(data.pronamespace) }}; +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/variables.sql new file mode 100644 index 000000000..5233c71ec --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/variables.sql @@ -0,0 +1,6 @@ +SELECT + name, vartype, min_val, max_val, enumvals +FROM + pg_settings +WHERE + context in ('user', 'superuser'); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/acl.sql new file mode 100644 index 000000000..ad3e0d156 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/acl.sql @@ -0,0 +1,35 @@ +SELECT + COALESCE(gt.rolname, 'public') AS grantee, + g.rolname AS grantor, array_agg(privilege_type) AS privileges, + array_agg(is_grantable) AS grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT + (d).grantee AS grantee, (d).grantor AS grantor, + (d).is_grantable AS is_grantable, + (d).privilege_type AS privilege_type + FROM + (SELECT aclexplode(db.proacl) AS d FROM pg_proc db + WHERE db.oid = {{fnid}}::OID) a + ) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/create.sql new file mode 100644 index 000000000..48a7a843a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/create.sql @@ -0,0 +1,57 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %} +{% set is_columns = [] %} +{% if data %} +CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data +.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}}{% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %},{% endif %} +{% endfor %} +{% endif -%} + ) + RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }} + LANGUAGE {{ data.lanname|qtLiteral }} + {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %}LEAKPROOF {% else %}NOT LEAKPROOF {% endif %} +{% if data.proisstrict %}STRICT {% endif %} +{% if data.prosecdef %}SECURITY DEFINER {% endif %} +{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %} + + COST {{data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %} +{% endif %} + +AS {% if data.lanname == 'c' %} +{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }} +{% else %} +$function$ +{{ data.prosrc }} +$function${% endif -%}; +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + OWNER TO {{ data.funcowner }}; +{% endif -%} +{% if data.acl %} +{% for p in data.acl %} + +{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}} +{% endfor %}{% endif %} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}}) + IS '{{ data.description }}'; +{% endif -%} +{% if data.seclabels %} +{% for r in data.seclabels %} +{% if r.security_label and r.provider %} + +{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }} +{% endif %} +{% endfor %} +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/delete.sql new file mode 100644 index 000000000..246bec12d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/delete.sql @@ -0,0 +1,21 @@ +{% if scid and fnid %} +SELECT + pr.proname as name, '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args, + nspname +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.oid = {{fnid}}; +{% endif %} + +{% if name %} +DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_definition.sql new file mode 100644 index 000000000..589eccee6 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_definition.sql @@ -0,0 +1,11 @@ +SELECT + pg_get_functiondef({{fnid}}::oid) AS func_def, + nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name +FROM + pg_proc pr +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND pr.oid = {{fnid}}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_languages.sql new file mode 100644 index 000000000..f81ddfbda --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_languages.sql @@ -0,0 +1,4 @@ +SELECT + lanname as label, lanname as value +FROM + pg_language; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_oid.sql new file mode 100644 index 000000000..2bc76a2e4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_oid.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace + AND nsp.nspname={{ nspname|qtLiteral }} +WHERE + proisagg = FALSE + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.proname = {{ name|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_out_types.sql new file mode 100644 index 000000000..64a11875f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_out_types.sql @@ -0,0 +1,6 @@ +SELECT + format_type(oid, NULL) AS out_arg_type +FROM + pg_type +WHERE + oid = {{ out_arg_oid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_schema.sql new file mode 100644 index 000000000..127d4b9db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_schema.sql @@ -0,0 +1,6 @@ +SELECT + nspname +FROM + pg_namespace +WHERE + oid = {{ scid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_types.sql new file mode 100644 index 000000000..2a5582ee9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_types.sql @@ -0,0 +1,20 @@ +SELECT + * +FROM + (SELECT + format_type(t.oid,NULL) AS typname, + CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname, + (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup + FROM + pg_type t + JOIN + pg_namespace nsp ON typnamespace=nsp.oid + WHERE + (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) + AND + ( + typtype IN ('b', 'c', 'd', 'e', 'p', 'r') + AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger') + ) + ) AS dummy +ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/node.sql new file mode 100644 index 000000000..c7f41596d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/node.sql @@ -0,0 +1,18 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' AS name, + lanname, pg_get_userbyid(proowner) AS funcowner, description +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pr.protype = '0'::char + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/properties.sql new file mode 100644 index 000000000..ff7829808 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/properties.sql @@ -0,0 +1,31 @@ +SELECT + pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c, + pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename, + typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames, + pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, + pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description, + (SELECT + array_agg(provider || '=' || label) + FROM + pg_shseclabel sl1 + WHERE + sl1.objoid=pr.oid) AS seclabels +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace typns ON typns.oid=typ.typnamespace +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +{% if fnid %} + AND pr.oid = {{fnid}}::oid +{% endif %} +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/update.sql new file mode 100644 index 000000000..c568d9844 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/update.sql @@ -0,0 +1,114 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %} +{% set name = o_data.name %} +{% if data.name %} +{% if data.name != o_data.name %} +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{ +o_data.proargtypenames }}) + RENAME TO {{ conn|qtIdent(data.name) }}; +{% set name = data.name %} +{% endif %} +{% endif -%} +{% if data.change_func %} + +CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %} +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %},{% endif %} +{% endfor %} +{% endif -%} +) + RETURNS {{ o_data.prorettypename }} +{% if 'lanname' in data %} + LANGUAGE {{ data.lanname|qtLiteral }} {% else %} + LANGUAGE {{ o_data.lanname|qtLiteral }} + {% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %} +{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %} LEAKPROOF{% elif 'proleakproof' in data and not data.proleakproof %} NOT LEAKPROOF{% endif %} +{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %} +{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} +{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %} + + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%} + {% endif %} + +AS {% if 'probin' in data or 'prosrc_c' in data %} +{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %} +$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %} +{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %} +$function${{ o_data.prosrc }}$function${% endif -%}; +{% endif -%} +{% if data.funcowner %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }}) + OWNER TO {{ data.funcowner }}; +{% endif -%} +{# The SQL generated below will change priviledges #} +{% if data.acl %} +{% if 'deleted' in data.acl %} +{% for priv in data.acl.deleted %} + +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in data.datacl %} +{% for priv in data.acl.changed %} + +{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in data.acl %} +{% for priv in data.acl.added %} + +{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %}{% endif -%} +{% endif -%} +{% if data.change_func == False %} +{% if data.variables %} +{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %} + +{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }} +{% endif -%} +{% if 'merged_variables' in data and data.merged_variables|length > 0 %} + +{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }} +{% endif -%} +{% endif -%} +{% endif -%} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} + +{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} + +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} + +{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if data.description %} + +COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }}) + IS {{ data.description|qtLiteral }}; +{% endif -%} + +{% if data.pronamespace %} + +ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }}) + SET SCHEMA {{ conn|qtIdent(data.pronamespace) }}; +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/variables.sql new file mode 100644 index 000000000..5233c71ec --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/variables.sql @@ -0,0 +1,6 @@ +SELECT + name, vartype, min_val, max_val, enumvals +FROM + pg_settings +WHERE + context in ('user', 'superuser'); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js new file mode 100644 index 000000000..e7132015d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js @@ -0,0 +1,184 @@ +/* Create and Register Procedure Collection and Node. */ +define( + ['jquery', 'underscore', 'underscore.string', + 'pgadmin', 'pgadmin.browser', 'alertify', + 'pgadmin.node.function', 'pgadmin.browser.collection', + 'pgadmin.browser.server.privilege'], +function($, _, S, pgAdmin, pgBrowser, alertify, Function) { + + if (!pgBrowser.Nodes['coll-procedure']) { + var procedures = pgAdmin.Browser.Nodes['coll-procedure'] = + pgAdmin.Browser.Collection.extend({ + node: 'procedure', + label: '{{ _('Procedures') }}', + type: 'coll-procedure', + columns: ['name', 'funcowner', 'description'] + }); + }; + + pgSchemaNode = pgBrowser.Nodes['schema']; + + // Inherit Functions Node + if (!pgBrowser.Nodes['procedure']) { + pgAdmin.Browser.Nodes['procedure'] = Function.extend({ + type: 'procedure', + label: '{{ _('Procedure') }}', + collection_type: 'coll-procedure', + hasSQL: true, + hasDepends: true, + parent_type: ['schema'], + Init: function() { + /* Avoid mulitple registration of menus */ + if (this.proc_initialized) + return; + + this.proc_initialized = true; + + pgBrowser.add_menus([{ + name: 'create_procedure_on_coll', node: 'coll-procedure', module: + this, + applies: ['object', 'context'], callback: 'show_obj_properties', + category: 'create', priority: 4, label: '{{ _('Procedure...') }}', + icon: 'wcTabIcon icon-procedure', data: {action: 'create', check: + false} + },{ + name: 'create_procedure', node: 'procedure', module: this, + applies: ['object', 'context'], callback: 'show_obj_properties', + category: 'create', priority: 4, label: '{{ _('Procedure...') }}', + icon: 'wcTabIcon icon-procedure', data: {action: 'create', check: + true}, + },{ + name: 'create_procedure', node: 'schema', module: this, + applies: ['object', 'context'], callback: 'show_obj_properties', + category: 'create', priority: 4, label: '{{ _('Procedure...') }}', + icon: 'wcTabIcon icon-procedure', data: {action: 'create', check: + true}, enable: 'canCreateProc' + } + ]); + }, + canDrop: pgSchemaNode.canChildDrop, + canDropCascade: pgSchemaNode.canChildDrop, + model: Function.model.extend({ + defaults: _.extend({}, + Function.model.prototype.defaults, + { + lanname: 'edbspl' + } + ), + canVarAdd: function(m){ + var server = this.node_info.server; + if (server.version < 90500) { + return false; + } + else { + return true; + } + }, + isVisible: function(m){ + if (this.name == 'sysfunc') { return false; } + else if (this.name == 'sysproc') { return true; } + return false; + }, + isDisabled: function(m) { + if(this.node_info && 'catalog' in this.node_info) { + return true; + } + name = this.name; + switch(name){ + case 'provolatility': + case 'proisstrict': + case 'prosecdef': + case 'procost': + case 'proleakproof': + case 'variables': + var server = this.node_info.server; + if (server.version < 90500) { + return true; + } + else { + return false; + } + break; + case 'prorows': + var server = this.node_info.server; + if(server.version >= 90500 && m.get('proretset') == true) { + return false; + } + else { + return true; + } + break; + case 'funcowner': + case 'lanname': + case 'proargs': + return true; + default: + return false; + break; + } + return false; + }, + validate: function() + { + var err = {}, + errmsg, + seclabels = this.get('seclabels'); + + if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { + err['name'] = '{{ _('Name can not be empty!') }}'; + errmsg = errmsg || err['name']; + } + + if (_.isUndefined(this.get('pronamespace')) || String(this.get('pronamespace')).replace(/^\s+|\s+$/g, '') == '') { + err['pronamespace'] = '{{ _('Schema can not be empty!') }}'; + errmsg = errmsg || err['pronamespace']; + } + + if (_.isUndefined(this.get('lanname')) || String(this.get('lanname')).replace(/^\s+|\s+$/g, '') == '') { + err['lanname'] = '{{ _('Language can not be empty!') }}'; + errmsg = errmsg || err['lanname']; + } + + if (_.isUndefined(this.get('prosrc')) || String(this.get('prosrc')).replace(/^\s+|\s+$/g, '') == '') { + err['prosrc'] = '{{ _('Code can not be empty!') }}'; + errmsg = errmsg || err['prosrc']; + } + + + if (seclabels) { + var secLabelsErr; + for (var i = 0; i < seclabels.models.length && !secLabelsErr; i++) { + secLabelsErr = (seclabels.models[i]).validate.apply(seclabels.models[i]); + if (secLabelsErr) { + err['seclabels'] = secLabelsErr; + errmsg = errmsg || secLabelsErr; + } + } + } + + this.errorModel.clear().set(err); + + return null; + }, + } + ), + canCreateProc: function(itemData, item, data) { + var node_hierarchy = this.getTreeNodeHierarchy.apply(this, [item]); + + // Do not provide Create option in catalog + if ('catalog' in node_hierarchy) + return false; + + // Procedures supported only in PPAS + if ('server' in node_hierarchy && node_hierarchy['server'].type == "ppas") + return true; + + return false; + + } + }); + + } + + return pgBrowser.Nodes['procedure']; +}); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/acl.sql new file mode 100644 index 000000000..ad3e0d156 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/acl.sql @@ -0,0 +1,35 @@ +SELECT + COALESCE(gt.rolname, 'public') AS grantee, + g.rolname AS grantor, array_agg(privilege_type) AS privileges, + array_agg(is_grantable) AS grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT + (d).grantee AS grantee, (d).grantor AS grantor, + (d).is_grantable AS is_grantable, + (d).privilege_type AS privilege_type + FROM + (SELECT aclexplode(db.proacl) AS d FROM pg_proc db + WHERE db.oid = {{fnid}}::OID) a + ) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/create.sql new file mode 100644 index 000000000..942181dc3 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/create.sql @@ -0,0 +1,33 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %} +{% set is_columns = [] %} +{% if data %} +CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if data.arguments %}( +{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %},{% endif %} +{% endfor %}) +{% endif %} + +AS +{{ data.prosrc }}; +{% if data.acl and not is_sql %} +{% for p in data.acl %} + +{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}} +{% endfor %}{% endif %} +{% if data.description %} + +COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }} + IS '{{ data.description }}'; +{% endif -%} +{% if data.seclabels %} +{% for r in data.seclabels %} +{% if r.label and r.provider %} + +{{ SECLABEL.SET(conn, 'PROCEDURE', data.name, r.provider, r.label, data.pronamespace, data.func_args) }} +{% endif %} +{% endfor %} +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/delete.sql new file mode 100644 index 000000000..18701ec7c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/delete.sql @@ -0,0 +1,21 @@ +{% if scid and fnid %} +SELECT + pr.proname as name, '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args, + nspname +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.oid = {{fnid}}; +{% endif %} + +{% if name %} +DROP PROCEDURE {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_definition.sql new file mode 100644 index 000000000..c635f1e36 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_definition.sql @@ -0,0 +1,12 @@ +SELECT + pg_get_functiondef({{fnid}}::oid) AS func_def, + nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name +FROM + pg_proc pr +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND pr.oid = {{fnid}}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_languages.sql new file mode 100644 index 000000000..f81ddfbda --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_languages.sql @@ -0,0 +1,4 @@ +SELECT + lanname as label, lanname as value +FROM + pg_language; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_oid.sql new file mode 100644 index 000000000..2bc76a2e4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_oid.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace + AND nsp.nspname={{ nspname|qtLiteral }} +WHERE + proisagg = FALSE + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.proname = {{ name|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_out_types.sql new file mode 100644 index 000000000..64a11875f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_out_types.sql @@ -0,0 +1,6 @@ +SELECT + format_type(oid, NULL) AS out_arg_type +FROM + pg_type +WHERE + oid = {{ out_arg_oid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_schema.sql new file mode 100644 index 000000000..127d4b9db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_schema.sql @@ -0,0 +1,6 @@ +SELECT + nspname +FROM + pg_namespace +WHERE + oid = {{ scid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_types.sql new file mode 100644 index 000000000..2a5582ee9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_types.sql @@ -0,0 +1,20 @@ +SELECT + * +FROM + (SELECT + format_type(t.oid,NULL) AS typname, + CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname, + (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup + FROM + pg_type t + JOIN + pg_namespace nsp ON typnamespace=nsp.oid + WHERE + (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) + AND + ( + typtype IN ('b', 'c', 'd', 'e', 'p', 'r') + AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger') + ) + ) AS dummy +ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/node.sql new file mode 100644 index 000000000..4b648c48b --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/node.sql @@ -0,0 +1,25 @@ +SELECT + pr.oid, + CASE WHEN + pg_catalog.pg_get_function_identity_arguments(pr.oid) <> '' + THEN + pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')' + ELSE + pr.proname + END AS name, + lanname, pg_get_userbyid(proowner) AS funcowner, description +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pr.protype = '1'::char + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/properties.sql new file mode 100644 index 000000000..9492f3c3d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/properties.sql @@ -0,0 +1,38 @@ +SELECT + pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c, + pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename, + typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames, + pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, + pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description, + (CASE WHEN + pg_catalog.pg_get_function_identity_arguments(pr.oid) <> '' + THEN + pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')' + ELSE + pr.proname + END) AS name_with_args, + (SELECT + array_agg(provider || '=' || label) + FROM + pg_seclabel sl1 + WHERE + sl1.objoid=pr.oid) AS seclabels +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace typns ON typns.oid=typ.typnamespace +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +{% if fnid %} + AND pr.oid = {{fnid}}::oid +{% endif %} +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/update.sql new file mode 100644 index 000000000..1cf2c10a4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/update.sql @@ -0,0 +1,82 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %}{% if data %} +{% set name = o_data.name %} +{% if data.name %} +{% if data.name != o_data.name %} +ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %} + + RENAME TO {{ conn|qtIdent(data.name) }}; +{% set name = data.name %} +{% endif %} + +{% endif -%} +{% if data.change_func %} +CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if data.arguments %}({% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %}, {% endif %} +{% endfor %} +) +{% endif %} + +AS +{% if data.prosrc %}{{ data.prosrc }}{% else %}{{ o_data.prosrc }}{% endif -%}; +{% endif -%} +{% if data.funcowner %} + +ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %} + OWNER TO {{ data.funcowner }}; +{% endif -%} +{# The SQL generated below will change priviledges #} +{% if data.acl %} +{% if 'deleted' in data.acl %} +{% for priv in data.acl.deleted %} + +{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in data.datacl %} +{% for priv in data.acl.changed %} + +{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, + priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in data.acl %} +{% for priv in data.acl.added %} + +{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif %} +{% endif -%} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} + +{{ SECLABEL.UNSET(conn, 'PROCEDURE', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} + +{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} + +{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if data.description %} + +COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }} + IS {{ data.description|qtLiteral }}; +{% endif -%} +{% if data.pronamespace %} + +ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }} + SET SCHEMA {{ conn|qtIdent(data.pronamespace) }}; +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/variables.sql new file mode 100644 index 000000000..5233c71ec --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/variables.sql @@ -0,0 +1,6 @@ +SELECT + name, vartype, min_val, max_val, enumvals +FROM + pg_settings +WHERE + context in ('user', 'superuser'); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/acl.sql new file mode 100644 index 000000000..ad3e0d156 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/acl.sql @@ -0,0 +1,35 @@ +SELECT + COALESCE(gt.rolname, 'public') AS grantee, + g.rolname AS grantor, array_agg(privilege_type) AS privileges, + array_agg(is_grantable) AS grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT + (d).grantee AS grantee, (d).grantor AS grantor, + (d).is_grantable AS is_grantable, + (d).privilege_type AS privilege_type + FROM + (SELECT aclexplode(db.proacl) AS d FROM pg_proc db + WHERE db.oid = {{fnid}}::OID) a + ) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/create.sql new file mode 100644 index 000000000..b1ee22c60 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/create.sql @@ -0,0 +1,33 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %} +{% set is_columns = [] %} +{% if data %} +CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if data.arguments %} +({% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %} {{ conn|qtIdent(p.argname)}}{% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %}, {% endif %} +{% endfor -%}){% endif %} + +AS +{{ data.prosrc }}; +{% if data.acl and not is_sql %} +{% for p in data.acl %} + +{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}} +{% endfor %}{% endif %} +{% if data.description %} + +COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }} + IS '{{ data.description }}'; +{% endif -%} +{% if data.seclabels %} +{% for r in data.seclabels %} +{% if r.security_label and r.provider %} + +{{ SECLABEL.SET(conn, 'PROCEDURE', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }} +{% endif %} +{% endfor %} +{% endif -%} + + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/delete.sql new file mode 100644 index 000000000..18701ec7c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/delete.sql @@ -0,0 +1,21 @@ +{% if scid and fnid %} +SELECT + pr.proname as name, '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args, + nspname +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.oid = {{fnid}}; +{% endif %} + +{% if name %} +DROP PROCEDURE {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_definition.sql new file mode 100644 index 000000000..c635f1e36 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_definition.sql @@ -0,0 +1,12 @@ +SELECT + pg_get_functiondef({{fnid}}::oid) AS func_def, + nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name +FROM + pg_proc pr +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND pr.oid = {{fnid}}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_languages.sql new file mode 100644 index 000000000..f81ddfbda --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_languages.sql @@ -0,0 +1,4 @@ +SELECT + lanname as label, lanname as value +FROM + pg_language; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_oid.sql new file mode 100644 index 000000000..2bc76a2e4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_oid.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace + AND nsp.nspname={{ nspname|qtLiteral }} +WHERE + proisagg = FALSE + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.proname = {{ name|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_out_types.sql new file mode 100644 index 000000000..64a11875f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_out_types.sql @@ -0,0 +1,6 @@ +SELECT + format_type(oid, NULL) AS out_arg_type +FROM + pg_type +WHERE + oid = {{ out_arg_oid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_schema.sql new file mode 100644 index 000000000..127d4b9db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_schema.sql @@ -0,0 +1,6 @@ +SELECT + nspname +FROM + pg_namespace +WHERE + oid = {{ scid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_types.sql new file mode 100644 index 000000000..2a5582ee9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_types.sql @@ -0,0 +1,20 @@ +SELECT + * +FROM + (SELECT + format_type(t.oid,NULL) AS typname, + CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname, + (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup + FROM + pg_type t + JOIN + pg_namespace nsp ON typnamespace=nsp.oid + WHERE + (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) + AND + ( + typtype IN ('b', 'c', 'd', 'e', 'p', 'r') + AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger') + ) + ) AS dummy +ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/node.sql new file mode 100644 index 000000000..4b648c48b --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/node.sql @@ -0,0 +1,25 @@ +SELECT + pr.oid, + CASE WHEN + pg_catalog.pg_get_function_identity_arguments(pr.oid) <> '' + THEN + pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')' + ELSE + pr.proname + END AS name, + lanname, pg_get_userbyid(proowner) AS funcowner, description +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pr.protype = '1'::char + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/properties.sql new file mode 100644 index 000000000..6cfec94aa --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/properties.sql @@ -0,0 +1,38 @@ +SELECT + pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c, + pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename, + typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames, + pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, + pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description, + (CASE WHEN + pg_catalog.pg_get_function_identity_arguments(pr.oid) <> '' + THEN + pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')' + ELSE + pr.proname + END) AS name_with_args, + (SELECT + array_agg(provider || '=' || label) + FROM + pg_shseclabel sl1 + WHERE + sl1.objoid=pr.oid) AS seclabels +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace typns ON typns.oid=typ.typnamespace +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +{% if fnid %} + AND pr.oid = {{fnid}}::oid +{% endif %} +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/update.sql new file mode 100644 index 000000000..4dd4637c5 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/update.sql @@ -0,0 +1,78 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %}{% if data %} +{% set name = o_data.name %} +{% if data.name %} +{% if data.name != o_data.name %} +ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, o_data.name) }} + RENAME TO {{ conn|qtIdent(data.name) }}; +{% set name = data.name %} +{% endif %} +{% endif -%} +{% if data.change_func %} + +CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if data.arguments %}({% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %}, {% endif %} +{% endfor %} +) +{% endif %} +AS {% if data.prosrc %}{{ data.prosrc }}{% else %}{{ o_data.prosrc }}{% endif -%}; +{% endif -%} +{% if data.funcowner %} + +ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %} + OWNER TO {{ data.funcowner }}; +{% endif -%} +{# The SQL generated below will change priviledges #} +{% if data.acl %} +{% if 'deleted' in data.acl %} +{% for priv in data.acl.deleted %} + +{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in data.acl %} +{% for priv in data.acl.changed %} + +{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in data.acl %} +{% for priv in data.acl.added %} + +{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif %} +{% endif -%} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} + +{{ SECLABEL.UNSET(conn, 'PROCEDURE', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} + +{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} + +{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if data.description %} + +COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }} + IS {{ data.description|qtLiteral }}; +{% endif -%} +{% if data.pronamespace %} + +ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }} + SET SCHEMA {{ conn|qtIdent(data.pronamespace) }}; +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/variables.sql new file mode 100644 index 000000000..5233c71ec --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/variables.sql @@ -0,0 +1,6 @@ +SELECT + name, vartype, min_val, max_val, enumvals +FROM + pg_settings +WHERE + context in ('user', 'superuser'); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/acl.sql new file mode 100644 index 000000000..ad3e0d156 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/acl.sql @@ -0,0 +1,35 @@ +SELECT + COALESCE(gt.rolname, 'public') AS grantee, + g.rolname AS grantor, array_agg(privilege_type) AS privileges, + array_agg(is_grantable) AS grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT + (d).grantee AS grantee, (d).grantor AS grantor, + (d).is_grantable AS is_grantable, + (d).privilege_type AS privilege_type + FROM + (SELECT aclexplode(db.proacl) AS d FROM pg_proc db + WHERE db.oid = {{fnid}}::OID) a + ) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/create.sql new file mode 100644 index 000000000..fd81c66e7 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/create.sql @@ -0,0 +1,43 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %} +{% set is_columns = [] %} +{% if data %} +CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if data.arguments %} +({% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %}, {% endif %} +{% endfor -%}){% endif %} + + {{ data.provolatile }}{% if data.proleakproof %} LEAKPROOF {% elif not data.proleakproof %} NOT LEAKPROOF {% endif %} +{% if data.proisstrict %}STRICT {% endif %} +{% if data.prosecdef %}SECURITY DEFINER {% endif %}{% if data.procost %} + + COST {{data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%} +{% endif %} + +AS +{{ data.prosrc }}; +{% if data.acl and not is_sql %} +{% for p in data.acl %} + +{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}} +{% endfor %}{% endif %} +{% if data.description %} + +COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }} + IS '{{ data.description }}'; +{% endif -%} +{% if data.seclabels %} +{% for r in data.seclabels %} +{% if r.security_label and r.provider %} + +{{ SECLABEL.SET(conn, 'PROCEDURE', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }} +{% endif %} +{% endfor %} +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/delete.sql new file mode 100644 index 000000000..18701ec7c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/delete.sql @@ -0,0 +1,21 @@ +{% if scid and fnid %} +SELECT + pr.proname as name, '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args, + nspname +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.oid = {{fnid}}; +{% endif %} + +{% if name %} +DROP PROCEDURE {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_definition.sql new file mode 100644 index 000000000..c635f1e36 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_definition.sql @@ -0,0 +1,12 @@ +SELECT + pg_get_functiondef({{fnid}}::oid) AS func_def, + nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name +FROM + pg_proc pr +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND pr.oid = {{fnid}}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_languages.sql new file mode 100644 index 000000000..f81ddfbda --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_languages.sql @@ -0,0 +1,4 @@ +SELECT + lanname as label, lanname as value +FROM + pg_language; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_oid.sql new file mode 100644 index 000000000..2bc76a2e4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_oid.sql @@ -0,0 +1,17 @@ +SELECT + pr.oid, pr.proname || '(' || COALESCE(pg_catalog + .pg_get_function_identity_arguments(pr.oid), '') || ')' as name, + lanname, pg_get_userbyid(proowner) as funcowner +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +JOIN + pg_namespace nsp ON nsp.oid=pr.pronamespace + AND nsp.nspname={{ nspname|qtLiteral }} +WHERE + proisagg = FALSE + AND typname NOT IN ('trigger', 'event_trigger') + AND pr.proname = {{ name|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_out_types.sql new file mode 100644 index 000000000..64a11875f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_out_types.sql @@ -0,0 +1,6 @@ +SELECT + format_type(oid, NULL) AS out_arg_type +FROM + pg_type +WHERE + oid = {{ out_arg_oid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_schema.sql new file mode 100644 index 000000000..127d4b9db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_schema.sql @@ -0,0 +1,6 @@ +SELECT + nspname +FROM + pg_namespace +WHERE + oid = {{ scid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_types.sql new file mode 100644 index 000000000..2a5582ee9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_types.sql @@ -0,0 +1,20 @@ +SELECT + * +FROM + (SELECT + format_type(t.oid,NULL) AS typname, + CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname, + (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup + FROM + pg_type t + JOIN + pg_namespace nsp ON typnamespace=nsp.oid + WHERE + (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) + AND + ( + typtype IN ('b', 'c', 'd', 'e', 'p', 'r') + AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger') + ) + ) AS dummy +ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/node.sql new file mode 100644 index 000000000..4b648c48b --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/node.sql @@ -0,0 +1,25 @@ +SELECT + pr.oid, + CASE WHEN + pg_catalog.pg_get_function_identity_arguments(pr.oid) <> '' + THEN + pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')' + ELSE + pr.proname + END AS name, + lanname, pg_get_userbyid(proowner) AS funcowner, description +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pr.protype = '1'::char + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/properties.sql new file mode 100644 index 000000000..6cfec94aa --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/properties.sql @@ -0,0 +1,38 @@ +SELECT + pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c, + pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename, + typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames, + pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, + pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description, + (CASE WHEN + pg_catalog.pg_get_function_identity_arguments(pr.oid) <> '' + THEN + pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')' + ELSE + pr.proname + END) AS name_with_args, + (SELECT + array_agg(provider || '=' || label) + FROM + pg_shseclabel sl1 + WHERE + sl1.objoid=pr.oid) AS seclabels +FROM + pg_proc pr +JOIN + pg_type typ ON typ.oid=prorettype +JOIN + pg_namespace typns ON typns.oid=typ.typnamespace +JOIN + pg_language lng ON lng.oid=prolang +LEFT OUTER JOIN + pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass) +WHERE + proisagg = FALSE + AND pronamespace = {{scid}}::oid + AND typname NOT IN ('trigger', 'event_trigger') +{% if fnid %} + AND pr.oid = {{fnid}}::oid +{% endif %} +ORDER BY + proname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/update.sql new file mode 100644 index 000000000..7777ccd69 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/update.sql @@ -0,0 +1,102 @@ +{% import 'macros/functions/security.macros' as SECLABEL %} +{% import 'macros/functions/privilege.macros' as PRIVILEGE %} +{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %} +{% set name = o_data.name %} +{% if data.name %} +{% if data.name != o_data.name %} +ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, o_data.name) }} + RENAME TO {{ conn|qtIdent(data.name) }}; +{% set name = data.name %} +{% endif %} +{% endif -%} +{% if data.change_func %} +CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if data.arguments %}({% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{p.argtype}}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %} +{% if not loop.last %}, {% endif %} +{% endfor %} +) +{% endif %} + {% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %}LEAKPROOF{% else %}NOT LEAKPROOF{% endif %} +{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %} +{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %} + + {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %} + + ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %} + + SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%} +{% endif %} + +AS +{% if data.prosrc %}{{ data.prosrc }}{% else %}{{ o_data.prosrc }}{% endif -%}; +{% endif -%} +{% if data.funcowner %} + +ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %} + OWNER TO {{ data.funcowner }}; +{% endif -%} +{# The SQL generated below will change priviledges #} +{% if data.acl %} +{% if 'deleted' in data.acl %} +{% for priv in data.acl.deleted %} + +{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in data.datacl %} +{% for priv in data.acl.changed %} + +{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }} + +{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in data.acl %} +{% for priv in data.acl.added %} + +{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif %} +{% endif -%} +{% if data.change_func == False %} +{% if data.variables %} +{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %} + +{{ VARIABLE.UNSET(conn, 'PROCEDURE', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }} +{% endif -%} +{% if 'merged_variables' in data and data.merged_variables|length > 0 %} + +{{ VARIABLE.SET(conn, 'PROCEDURE', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }} +{% endif -%} +{% endif -%} +{% endif -%} +{% set seclabels = data.seclabels %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} + +{{ SECLABEL.UNSET(conn, 'PROCEDURE', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} + +{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} + +{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }} +{% endfor %} +{% endif -%} +{% if data.description %} + +COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }} + IS {{ data.description|qtLiteral }}; +{% endif -%} +{% if data.pronamespace %} + +ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }} + SET SCHEMA {{ conn|qtIdent(data.pronamespace) }}; +{% endif -%} + +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/variables.sql new file mode 100644 index 000000000..5233c71ec --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/variables.sql @@ -0,0 +1,6 @@ +SELECT + name, vartype, min_val, max_val, enumvals +FROM + pg_settings +WHERE + context in ('user', 'superuser');