Hi,
PFA patch for cast module.
Please do review it and let me know in case of any issue.
Regards,
Sanket Mehta
Sr Software engineer
Enterprisedb
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py
new file mode 100644
index 0000000..edb937b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py
@@ -0,0 +1,470 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2015, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import json
+from flask import render_template, make_response, current_app, request, jsonify
+from flask.ext.babel import gettext
+from pgadmin.utils.ajax import make_json_response, \
+ make_response as ajax_response, internal_server_error
+from pgadmin.browser.utils import NodeView
+from pgadmin.browser.collection import CollectionNodeModule
+import pgadmin.browser.server_groups.servers.databases as databases
+from pgadmin.utils.ajax import precondition_required
+from pgadmin.utils.driver import get_driver
+from config import PG_DEFAULT_DRIVER
+from functools import wraps
+
+
+class CastModule(CollectionNodeModule):
+ NODE_TYPE = 'cast'
+ COLLECTION_LABEL = 'Casts'
+
+ def __init__(self, *args, **kwargs):
+ super(CastModule, self).__init__(*args, **kwargs)
+
+ def get_nodes(self, gid, sid, did):
+ """
+ Generate the collection node
+ """
+ yield self.generate_browser_collection_node(did)
+
+ @property
+ def script_load(self):
+ """
+ Load the module script for server, when any of the server-group node is
+ initialized.
+ """
+ return databases.DatabaseModule.NODE_TYPE
+
+
+blueprint = CastModule(__name__)
+
+
+class CastView(NodeView):
+ node_type = blueprint.node_type
+
+
+ parent_ids = [
+ {'type': 'int', 'id': 'gid'},
+ {'type': 'int', 'id': 'sid'},
+ {'type': 'int', 'id': 'did'}
+ ]
+ ids = [
+ {'type': 'int', 'id': 'cid'}
+ ]
+
+ operations = dict({
+ 'obj': [
+ {'get': 'properties', 'delete': 'delete', 'put': 'update'},
+ {'get': 'list', 'post': 'create'}
+ ],
+ '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'}],
+ 'configs': [{'get': 'configs'}],
+ 'get_type': [{'get': 'get_sourceTarget_type'}, {'get': 'get_sourceTarget_type'}],
+ 'getfunctions': [{'post': 'get_functions'}, {'post': 'get_functions'}]
+ })
+
+ def module_js(self):
+ """
+ This property defines (if javascript) exists for this node.
+ Override this property for your own logic.
+ """
+ return make_response(
+ render_template(
+ "cast/js/casts.js",
+ _=gettext
+ ),
+ 200, {'Content-Type': 'application/x-javascript'}
+ )
+
+ def check_precondition(f):
+ """
+ This function will behave as a decorator which will checks
+ database connection before running view, it will also attaches
+ manager,conn & template_path properties to self
+ """
+ @wraps(f)
+ def wrap(*args, **kwargs):
+ # Here args[0] will hold self & kwargs will hold gid,sid,did
+ self = args[0]
+ self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid'])
+ self.conn = self.manager.connection(did=kwargs['did'])
+ # If DB not connected then return error to browser
+ if not self.conn.connected():
+ return precondition_required(
+ gettext(
+ "Connection to the server has been lost!"
+ )
+ )
+ ver = self.manager.version
+ # we will set template path for sql scripts
+ if ver >= 90000:
+ self.template_path = 'cast/sql/9.0_plus'
+
+ return f(*args, **kwargs)
+
+ return wrap
+
+
+ @check_precondition
+ def list(self, gid, sid, did):
+ SQL = render_template(
+ "/".join([self.template_path, 'properties.sql']),
+ datlastsysoid=self.manager.db_info[did]['datlastsysoid']
+ )
+ 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):
+ res = []
+ SQL = render_template(
+ "/".join([self.template_path, 'properties.sql']),
+ datlastsysoid=self.manager.db_info[did]['datlastsysoid']
+ )
+ 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'],
+ row['name'],
+ icon="icon-cast"
+ ))
+
+ return make_json_response(
+ data=res,
+ status=200
+ )
+
+ @check_precondition
+ def properties(self, gid, sid, did, cid):
+ SQL = render_template(
+ "/".join([self.template_path, 'properties.sql']),
+ cid=cid,
+ datlastsysoid=self.manager.db_info[did]['datlastsysoid']
+ )
+ status, res = self.conn.execute_dict(SQL)
+
+ if not status:
+ return internal_server_error(errormsg=res)
+
+ return ajax_response(
+ response=res['rows'][0],
+ status=200
+ )
+
+ @check_precondition
+ def create(self, gid, sid, did):
+ """
+ This function will creates new the cast object
+ """
+
+ required_args = [
+ 'srctyp',
+ 'trgtyp'
+ ]
+
+ data = request.form if request.form else json.loads(request.data.decode())
+ for arg in required_args:
+ if arg not in data:
+ return make_json_response(
+ status=410,
+ success=0,
+ errormsg=gettext(
+ "Couldn't find the required parameter (%s)." % arg
+ )
+ )
+ try:
+ SQL = render_template("/".join([self.template_path, 'create.sql']),
+ data=data
+ )
+ status, res = self.conn.execute_scalar(SQL)
+ if not status:
+ return internal_server_error(errormsg=res)
+
+ # we need oid to to add object in tree at browser, below sql will gives the same
+ SQL = render_template("/".join([self.template_path, 'grant.sql']),
+ srctyp=data.srctyp,
+ trgtyp=data.trgtyp,
+ datlastsysoid=self.manager.db_info[did]['datlastsysoid']
+ )
+ status, cid = self.conn.execute_scalar(SQL)
+ if not status:
+ return internal_server_error(errormsg=cid)
+
+ return jsonify(
+ node=self.blueprint.generate_browser_node(
+ cid,
+ data['name'],
+ icon="pg-icon-cast"
+ )
+ )
+ except Exception as e:
+ return internal_server_error(errormsg=str(e))
+
+
+ @check_precondition
+ def update(self, gid, sid, did, cid):
+ """
+ This function will update cast object
+ """
+ data = request.form if request.form else json.loads(request.data.decode())
+ SQL = self.getSQL(gid, sid, data, cid)
+ 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="Cast updated",
+ data={
+ 'id': cid,
+ 'sid': sid,
+ 'gid': gid,
+ 'did': did
+ }
+ )
+ else:
+ return make_json_response(
+ success=1,
+ info="Nothing to update",
+ data={
+ 'id': cid,
+ 'sid': sid,
+ 'gid': gid,
+ 'did': did
+ }
+ )
+
+ except Exception as e:
+ return internal_server_error(errormsg=str(e))
+
+ @check_precondition
+ def delete(self, gid, sid, did, cid):
+ """
+ This function will drop the cast object
+ """
+ # Below will decide if it's simple drop or drop with cascade call
+ if self.cmd == 'delete':
+ # This is a cascade operation
+ cascade = True
+ else:
+ cascade = False
+
+ try:
+ # Get name for cast from cid and drop it
+ SQL = render_template("/".join([self.template_path, 'delete.sql']),
+ cid=cid,
+ 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("Cast dropped"),
+ data={
+ 'id': cid,
+ 'sid': sid,
+ 'gid': gid,
+ 'did': did
+ }
+ )
+
+ except Exception as e:
+ return internal_server_error(errormsg=str(e))
+
+ @check_precondition
+ def msql(self, gid, sid, did, cid=None):
+ """
+ This function returns modified SQL
+ """
+ data = request.args
+ SQL = self.getSQL(gid, sid, did, data, cid)
+ if isinstance(SQL, str) and SQL and SQL.strip('\n') and SQL.strip(' '):
+ return make_json_response(
+ data=SQL,
+ status=200
+ )
+ else:
+ return make_json_response(
+ data="--modified SQL",
+ status=200
+ )
+
+ def getSQL(self, gid, sid, did, data, cid=None):
+ """
+ This function will return SQL for model data
+ """
+ try:
+ if cid is not None:
+ SQL = render_template("/".join([self.template_path, 'properties.sql']),
+ cid=cid,
+ datlastsysoid=self.manager.db_info[did]['datlastsysoid'])
+ status, res = self.conn.execute_dict(SQL)
+
+ if not status:
+ return internal_server_error(errormsg=res)
+
+ old_data = res['rows'][0]
+ SQL = render_template(
+ "/".join([self.template_path, 'update.sql']),
+ data=data, o_data=old_data
+ )
+ else:
+ if 'srctyp' in data and 'trgtyp' in data:
+ SQL = render_template("/".join([self.template_path, 'create.sql']), data=data)
+ SQL += "\n"
+ SQL += render_template("/".join([self.template_path, 'grant.sql']), data=data)
+ else:
+ SQL = "-- incomplete definition"
+ return SQL
+
+ except Exception as e:
+ return internal_server_error(errormsg=str(e))
+
+ @check_precondition
+ def get_functions(self, gid, sid, did, cid=None):
+ res=[]
+ data = request.form if request.form else json.loads(request.data.decode())
+ #srcOid = data['srctyp'].split(":")[0]
+ #trgOid = data['trgtyp'].split(":")[0]
+ SQL = render_template("/".join([self.template_path, 'functions.sql']),
+ srctyp=data['srctyp'],
+ trgtyp=data['trgtyp'])
+ status, rset = self.conn.execute_dict(SQL)
+
+ if not status:
+ return internal_server_error(errormsg=rset)
+
+ # TODO: add schemaprefix to proname before adding it to value in res
+ for row in rset['rows']:
+ res.append({'label': row['proname'],
+ 'value': row['proname']})
+ return make_json_response(
+ data=res,
+ status=200
+ )
+
+ @check_precondition
+ def get_sourceTarget_type(self, gid, sid, did, cid=None):
+ res = []
+ SQL = render_template(
+ "/".join([self.template_path, 'getsrcandtrgttype.sql']),
+ cid=cid
+ )
+ status, rset = self.conn.execute_dict(SQL)
+
+ if not status:
+ return internal_server_error(errormsg=rset)
+
+ res = [{'label': '', 'value': ''}]
+ for row in rset['rows']:
+ # TODO: Follow dlgTypeProperty::FillDataType() function before adding typename to res
+ res.append({'label': row['typname'],
+ 'value': row['typname']})
+
+
+ print(res)
+ return make_json_response(
+ data=res,
+ status=200
+ )
+
+
+ """def getDataType(self, resultRow, numdims=0, typmod = -1):
+
+ nspname = resultRow['nspname']
+ typname = resultRow['typname']
+ isdup = resultRow['isdup']
+ name = ""
+ array = ""
+ length = ""
+ prec = 0
+ len = 0
+ if str(nspname + '\".') in typname:
+ name = typname[nspname.len() + 3] # "+2" because of the two double quotes
+ elif str(nspname + ".") in typname:
+ name = typname[nspname.len() + 1]
+ else:
+ name = typname
+
+ if name.startswith("_"):
+ if not numdims:
+ numdims = 1
+ name = name[1]
+ if name[-2:] == str("[]"):
+ if not numdims:
+ numdims = 1
+ name = name[name.len() - 2]
+
+ if name.startswith('\"') and name.endswith('\"'):
+ name = name[1, name.len() - 2]
+
+ if numdims > 0:
+ while numdims-- :
+ array += str("[]")
+
+ if typmod != -1:
+ length = str("(")
+ if name == str("numeric"):
+ len = (typmod - 4L) >> 16L
+ prec = (typmod - 4) & 0xffff
+ length += str(len)
+ if prec:
+ length += str(",") + str(prec)
+
+ elif name == str("time") or name == str("timetz") \
+ or name == str("time without time zone") or name == str("time with time zone") \
+ or name == str("timestamp") or name == str("timestamptz") \
+ or name == str("timestamp without time zone") or name == str("timestamp with time zone") \
+ or name == str("bit") or name == str("bit varying") or name == str("varbit"):
+ prec = 0
+ len = typmod
+ length += str(len)
+
+ elif name == str("interval"):
+ prec = 0
+ len = (typmod & 0xffff)
+ length += str(len)
+
+ elif name == str("date"):
+ len = prec = 0
+ length = str("") #Clear Length
+
+ else:
+ prec = 0
+ len = typmod - 4L
+ length += str(len)
+
+ if length.len() > 0:
+ length += str(")")
+ else:
+ len = prec = 0"""
+CastView.register_node_view(blueprint)
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/static/img/cast-sm.png b/web/pgadmin/browser/server_groups/servers/databases/casts/static/img/cast-sm.png
new file mode 100644
index 0000000000000000000000000000000000000000..52b775538d0fa24e280d595b8d08eccad868fc9f
GIT binary patch
literal 385
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}Y=BRQE0Es3wsvWsO@89kNdH}P
zr(Zj=J^k)|iTb?irAz-G-&J<+f#RxF|M#vbc=$+v<Hr9_p4#u)_5bMhgy$~;4<G*j
z>Q&0wv;W_|ExmT_|A+T&_wWDz^l9?5Xa7&_?Wrr6y|pSR3}^vkNswPKgTu2MX+REV
zfk$L9koEv$x0Bg+Kt{Bui(`ny<*9wA#T*O-oVD2&UYWh>`2YH4>$a5LxjT3A$<Cnr
z9uvI8D*Kw2vaDZV`nn(^p(jzg?n32_)54MrJ#$<Z#hr<<S;(fnc57kM;^L1&Z*1aD
z`^D)0KhAr=kvV?bYX*CuHL4}95hW>!C8<`)MX5lF!N|bSK-bVn*T68u$iT|P*viC2
z+rZSyz`$arsvL@j-29Zxv`UBu152<5kZLOfGl+&$(?iz)H86O(`njxgN@xNAxrdn&
literal 0
HcmV?d00001
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/static/img/cast.png b/web/pgadmin/browser/server_groups/servers/databases/casts/static/img/cast.png
new file mode 100644
index 0000000000000000000000000000000000000000..2be7f3742a760faa7709052669f444ba8949c330
GIT binary patch
literal 426
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}a)3{WE0A8=XLIY~`bhs>bEjXs
zdtc(<#)_V{^GlchKee~#-UGQ6EB@bqsIhL{|A&u_H*fy`<f;9xUH_jw_c?g*|BIJV
zCr<o-{W{~qh5v8gmR`H||NZ->d-wi-{Mh^W@&C`CroDLaf6w;E(Q{(sfz~jV1o;Is
zI6S+N2IO!SctjQhX%8@VJDF_<WYl@OIEF}E&OLuysL4Qp`NFZQywjDGIy`p%_#dBn
zQ0(`EO7CUHXQe*N`?)=t^Q7D8w8}9V*M&OXmYcSQMTTxXa5eZ^sYbzVjoHtlAM6X>
zw)Vt7;XUhu?aCg8-q)T#djsp?1vQn0(#HZ{&avK>G;7M|Kezi*1J|9@wM@A8GIu5a
z7k@SvKA%lLfi6)kag8WRNi0dVN-jzTQVd20h6cKZM!E)uAw~vPCdO7KCfWw3Rt5$Z
sGgakKH00)|WTsU@G#FTdHGouG8JIydoSGiG2B?9-)78&qol`;+06z@3hyVZp
literal 0
HcmV?d00001
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/static/img/coll-cast.png b/web/pgadmin/browser/server_groups/servers/databases/casts/static/img/coll-cast.png
new file mode 100644
index 0000000000000000000000000000000000000000..09eb65af02c66bd64ab3405c592efe4d90d41c98
GIT binary patch
literal 402
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}RDe&2E08|5w`XaeO<lq4NdH}P
zr(e5!U!p#*dg;>t_Z}!tZ4Ap#oci#Q{=SXoPoCQE-(<UL)&Gqf|L@xM|LFFF=Pv>e
zAO8R0ecP*7DQD0A|MY3{+qb3HuKmA%|NpaR|1ZhRj0c*|SQ6wH%;50sMjDXAS>O>_
z45U54*zIJt9gval>Eak7ak=#TZN6p&0hSA?yGp&5X6Q%he*0e^ToZZWNTsr+b)t)l
zj9%4Lq4qZOwfFDczc{Oq<6)rmksEJ&nEiOFw@y3DVz*ZO=8+TAZ=JQC&Ch=IlJ%q0
zn#a%d$On5}eQ!_{`O0<1PkWs^`g)O!!JAm-u{;Xg4zyae#5JNMC9x#cD!C{XNHG{0
z7#ipr8tEDsh8P)GnHXD{m}ncAS{WEv%v6;_(U6;;l9^Ts(O_T+)&Np%Wnc!;aB6z!
Q8lVOSPgg&ebxsLQ09Xf~fdBvi
literal 0
HcmV?d00001
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/js/casts.js b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/js/casts.js
new file mode 100644
index 0000000..501b878
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/js/casts.js
@@ -0,0 +1,183 @@
+define(
+ ['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'],
+function($, _, S, pgAdmin, pgBrowser, alertify) {
+
+ if (!pgBrowser.Nodes['coll-cast']) {
+ var casts = pgAdmin.Browser.Nodes['coll-cast'] =
+ pgAdmin.Browser.Collection.extend({
+ node: 'cast',
+ label: '{{ _('Casts') }}',
+ type: 'coll-cast'
+ });
+ };
+
+ if (!pgBrowser.Nodes['cast']) {
+ pgAdmin.Browser.Nodes['cast'] = pgAdmin.Browser.Node.extend({
+ parent_type: 'database',
+ type: 'cast',
+ label: '{{ _('Cast') }}',
+ hasSQL: true,
+ Init: function() {
+ /* Avoid mulitple registration of menus */
+ if (this.initialized)
+ return;
+
+ this.initialized = true;
+
+ pgBrowser.add_menus([{
+ name: 'create_cast_on_database', node: 'database', module: this,
+ applies: ['object', 'context'], callback: 'show_obj_properties',
+ category: 'create', priority: 4, label: '{{ _('Cast...') }}',
+ icon: 'wcTabIcon icon-cast', data: {action: 'create'}
+ },{
+ name: 'create_cast_on_coll', node: 'coll-cast', module: this,
+ applies: ['object', 'context'], callback: 'show_obj_properties',
+ category: 'create', priority: 4, label: '{{ _('Cast...') }}',
+ icon: 'wcTabIcon icon-cast', data: {action: 'create'}
+ },{
+ name: 'create_cast', node: 'cast', module: this,
+ applies: ['object', 'context'], callback: 'show_obj_properties',
+ category: 'create', priority: 4, label: '{{ _('Cast...') }}',
+ icon: 'wcTabIcon icon-cast', data: {action: 'create'}
+ },{
+ name: 'drop_cast', node: 'cast', module: this,
+ applies: ['object', 'context'], callback: 'delete_obj',
+ category: 'drop', priority: 4, label: '{{ _('Delete/Drop Cast...') }}',
+ icon: 'fa fa-thrash'
+ },{
+ name: 'drop_cascaded_cast', node: 'cast', module: this,
+ applies: ['object', 'context'], callback: 'delete_obj_cascade',
+ category: 'drop', priority: 4, label: '{{ _('Drop Cascaded...') }}',
+ icon: 'fa fa-thrash'
+ }]);
+
+ },
+ model: pgAdmin.Browser.Node.Model.extend({
+ defaults: {
+ name: undefined,
+ comment: undefined,
+ encoding: 'UTF8',
+ srctyp: undefined,
+ trgtyp: undefined,
+ proname: undefined,
+ castcontext: undefined,
+ syscast: undefined,
+ description: undefined
+ },
+ schema: [{
+ id: 'name', label: '{{ _('Name') }}', cell: 'string', group: '{{ _('Definition') }}',
+ editable: false, type: 'text', disabled: true
+ },{
+ id: 'oid', label:'{{ _('Oid') }}', cell: 'string', group: '{{ _('Definition') }}',
+ editable: false, type: 'text', disabled: true,
+ },{
+ id: 'srctyp', label:'{{ _('Source type') }}', url: 'get_type',
+ type: 'text', group: 'Definition', disabled: function(m) {
+ return !m.isNew()
+ },
+ transform: function(rows) {
+ _.each(rows, function(r) {
+ r['image'] = 'icon-cast';
+ });
+ return rows;
+ },
+ control: Backform.NodeAjaxOptionsControl.extend({
+ onChange: function() {
+ console.log(this.$el.find("select").val());
+ Backform.NodeAjaxOptionsControl.prototype.onChange.apply(this, arguments);
+ var srcType = this.model.get('srctyp');
+ var trgtype = this.model.get('trgtyp');
+ if(srcType != undefined && srcType != '' && trgtype != undefined && trgtype != '')
+ this.model.set("name", srcType+"->"+trgtype);
+ else
+ this.model.unset("name");
+ }
+ })
+ },{
+ id: 'trgtyp', label:'{{ _('Target type') }}', url: 'get_type',
+ type: 'text', group: 'Definition', disabled: function(m) {
+ return !m.isNew()
+ },
+ transform: function(rows) {
+ _.each(rows, function(r) {
+ r['image'] = 'icon-cast';
+ });
+ return rows;
+ },
+ control: Backform.NodeAjaxOptionsControl.extend({
+ onChange: function() {
+ Backform.NodeAjaxOptionsControl.prototype.onChange.apply(this, arguments);
+ var srcType = this.model.get('srctyp');
+ var trgtype = this.model.get('trgtyp');
+ if(srcType != undefined && srcType != '' && trgtype != undefined && trgtype != '')
+ this.model.set("name", srcType+"->"+trgtype);
+ else
+ this.model.unset("name");
+ }
+ })
+ },{
+ id: 'proname', label:'{{ _('Function') }}', deps:['srctyp', 'trgtyp'],
+ editable: false, type: 'text', disabled: function(m) { return !m.isNew(); },
+ group: 'Definition',
+ control: 'select', options: function() {
+ /*
+ * TODO::
+ * Make ajax call here and return it as an array of object
+ * {label: <LABEL>, value: <LABEL>}
+ */
+ var srcTyp = this.model.get('srctyp');
+ var trgtyp = this.model.get('trgtyp');
+ var res = [];
+
+ if(srcTyp != undefined && srcTyp != '' && trgtyp != undefined && trgtyp != '')
+ {
+ var node = this.field.get('schema_node'),
+ _url = node.generate_url.apply(
+ node, [
+ null, 'getfunctions', this.field.get('node_data'), false,
+ this.field.get('node_info')
+ ]);
+ $.ajax({
+ type: 'POST',
+ timeout: 30000,
+ url: _url,
+ cache: false,
+ //data: this.model.toJSON(true, 0, 'POST'),
+ data: {"srctyp" : srcTyp, "trgtyp" : trgtyp},
+ success: function(res) {
+ console.log(res);
+ // append to res
+ return res.data;
+ //this.model.set('proname',res.data);
+ },
+ error: function(xhr, status, error) {
+ try {
+ var err = $.parseJSON(xhr.responseText);
+ if (err.success == 0) {
+ msg = S('{{ _(' + err.errormsg + ')}}').value();
+ alertify.error("{{ _('" + err.errormsg + "') }}");
+ }
+ } catch (e) {}
+ }
+ });
+ }
+ return res;
+ }
+ },{
+ id: 'castcontext', label:'{{ _('Context') }}', options:{'onText':'Implicit','offText':'Explicit'},
+ editable: false, type: 'switch', disabled: function(m) { return !m.isNew(); },
+ group: 'Definition'
+ },{
+ id: 'syscast', label:'{{ _('System Cast?') }}', mode: ['properties'],
+ editable: false, type: 'text'
+ },{
+ id: 'description', label:'{{ _('Comment') }}', group: '{{ _('Definition') }}',
+ type: 'text', group: 'Properties'
+ }
+ ]
+ })
+ });
+
+ }
+ return pgBrowser.Nodes['coll-cast'];
+});
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/create.sql
new file mode 100644
index 0000000..160686a
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/create.sql
@@ -0,0 +1,11 @@
+{# ========== Below SQL will create cast =========== #}
+{% if data and data.srctyp and data.trgtyp %}
+CREATE CAST ({{data.srctyp}} AS {{data.trgtyp}})
+{% if data.proname %}
+WITH FUNCTION {{data.proname}}
+{% else %} WITHOUT FUNCTION
+{% endif %}
+{% if data.castcontext == True %}
+AS IMPLICIT
+{% endif %};
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/delete.sql
new file mode 100644
index 0000000..bb1635f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/delete.sql
@@ -0,0 +1,10 @@
+{% if cid %}
+SELECT
+ ca.castsource in castsource,
+ ca.casttarget in casttarget
+FROM
+ pg_cast ca
+WHERE
+ ca.oid = {{cid}}::OID
+{% endif %}
+DROP CAST (conn|qtIdent(castsource) AS conn|qtIdent(casttarget)) {% if cascade %}CASCADE{%endif%};
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/functions.sql b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/functions.sql
new file mode 100644
index 0000000..83a2e3d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/functions.sql
@@ -0,0 +1,11 @@
+SELECT
+ proname,
+ nspname,
+ proargtypes
+FROM
+ pg_proc p JOIN pg_namespace n ON n.oid=p.pronamespace
+WHERE
+ proargtypes[0] = (SELECT t.oid FROM pg_type t WHERE format_type(t.oid, NULL) = {{srctyp|qtLiteral}})
+ AND COALESCE(p.proargtypes[1], 0) = 0
+ AND prorettype = (SELECT t.oid FROM pg_type t WHERE format_type(t.oid, NULL) = {{trgtyp|qtLiteral}})
+
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/getsrcandtrgttype.sql b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/getsrcandtrgttype.sql
new file mode 100644
index 0000000..3d5601c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/getsrcandtrgttype.sql
@@ -0,0 +1,41 @@
+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 typisdefined
+ AND typtype IN ('b', 'c', 'e', 'r')
+ AND NOT EXISTS (SELECT
+ 1
+ FROM
+ pg_class
+ WHERE
+ relnamespace = typnamespace
+ AND relname = typname
+ AND relkind != 'c')
+ AND (typname NOT LIKE '_%'
+ OR NOT EXISTS (SELECT
+ 1
+ FROM
+ pg_class
+ WHERE
+ relnamespace = typnamespace
+ AND relname = SUBSTRING(typname FROM 2)::name
+ AND relkind != 'c'))
+ AND nsp.nspname != 'information_schema' ) AS dummy
+ORDER BY
+ nspname <> 'pg_catalog', nspname <> 'public', nspname, 1
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/grant.sql
new file mode 100644
index 0000000..64fce3d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/grant.sql
@@ -0,0 +1,17 @@
+{# ========== Below creates description for cast =========== #}
+{% if data.description %}
+COMMENT ON CAST ({{ data.srctyp }} AS {{ data.trgtyp }})
+ IS {{ data.description|qtLiteral }};
+{% endif %}
+{# ======== Below SQL will fetch id for given cast ======== #}
+{% if srctyp and trgtyp %}
+SELECT
+ ca.oid
+FROM pg_cast ca
+WHERE pg_cast.castsource = (SELECT t.oid FROM pg_type t WHERE format_type(t.oid, NULL) = {{srctyp|qtLiteral}})
+AND pg_cast.casttarget = (SELECT t.oid FROM pg_type t WHERE format_type(t.oid, NULL) = {{trgtyp|qtLiteral}})
+ {% if datlastsysoid %}
+ AND ca.oid > {{datlastsysoid}}::OID
+ {% endif %}
+{% endif %}
+
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/properties.sql
new file mode 100644
index 0000000..edca24f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/properties.sql
@@ -0,0 +1,45 @@
+SELECT
+ ca.oid,
+CASE
+ WHEN {{datlastsysoid}}::OID > ca.oid then 'YES' ELSE 'NO'
+END AS syscast,
+CASE
+ WHEN ca.castcontext = 'a' THEN 'ASSIGNMENT'
+ WHEN ca.castcontext = 'i' THEN 'IMPLICIT'
+ WHEN ca.castcontext = 'e' THEN 'EXPLICIT'
+END AS castcontext,
+CASE
+ WHEN proname IS NULL THEN 'binary compatible'
+END AS proname,
+ ca.castfunc,
+ format_type(st.oid,NULL) AS srctyp,
+ format_type(tt.oid,tt.typtypmod) AS trgtyp,
+ ns.nspname AS srcnspname,
+ nt.nspname AS trgnspname,
+ np.nspname AS pronspname,
+ description,
+ concat(format_type(st.oid,NULL),'->',format_type(tt.oid,tt.typtypmod)) as name
+FROM pg_cast ca
+JOIN pg_type st ON st.oid=castsource
+JOIN pg_namespace ns ON ns.oid=st.typnamespace
+JOIN pg_type tt ON tt.oid=casttarget
+JOIN pg_namespace nt ON nt.oid=tt.typnamespace
+LEFT JOIN pg_proc pr ON pr.oid=castfunc
+LEFT JOIN pg_namespace np ON np.oid=pr.pronamespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=ca.oid AND des.objsubid=0 AND des.classoid='pg_cast'::regclass)
+
+{% if cid %}
+WHERE ca.oid={{cid}}::int
+{% endif %}
+
+--TODO: add check for showSystemObject(). currently assumed as false
+{% if datlastsysoid %}
+{% if cid %}
+AND
+{% else %}
+WHERE
+{% endif %}
+ca.oid > {{datlastsysoid}}::OID
+{% endif %}
+
+ORDER BY st.typname, tt.typname
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/update.sql
new file mode 100644
index 0000000..1a34693
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/cast/sql/9.0_plus/update.sql
@@ -0,0 +1,6 @@
+{# ===========Below SQL will update cast comments=================== #}
+
+{% if data and data.description and data.description != o_data.description %}
+COMMENT ON CAST ({{o_data.srctyp}} AS {{o_data.trgtyp}})
+ IS {{ data.description }};
+{% endif %}
\ No newline at end of file
--
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers