pgtoolkit/pgbrowser.py
changeset 59 65efd0c6919f
parent 58 0bcc13460dae
child 68 b0d972be2631
equal deleted inserted replaced
58:0bcc13460dae 59:65efd0c6919f
   111             self.refresh_indexes()
   111             self.refresh_indexes()
   112         return self._indexes
   112         return self._indexes
   113     indexes = property(getindexes)
   113     indexes = property(getindexes)
   114 
   114 
   115 
   115 
       
   116 class Argument:
       
   117     def __init__(self, browser, function, name, type, mode, default):
       
   118         # PgBrowser instance
       
   119         self.browser = browser
       
   120         # Function instance
       
   121         self.function = function
       
   122         self.name = name
       
   123         self.type = type
       
   124         self.mode = mode
       
   125         self.default = default
       
   126 
   116 class Function:
   127 class Function:
   117     def __init__(self, browser, schema, oid, name, type, arguments, result, source):
   128     def __init__(self, browser, schema, oid, name, function_name, type, result, source):
   118         self.browser = browser
   129         self.browser = browser
       
   130         self.schema = schema
   119         self.oid = oid
   131         self.oid = oid
   120         self.name = name
   132         #: unique name - function name + arg types
       
   133         self.name = name
       
   134         #: pure function name without args
       
   135         self.function_name = function_name
   121         self.type = type
   136         self.type = type
   122         self.arguments = arguments
       
   123         self.result = result
   137         self.result = result
   124         self.source = source
   138         self.source = source
       
   139         self._arguments = None
   125         self._definition = None
   140         self._definition = None
       
   141 
       
   142     def refresh(self):
       
   143         self.refresh_args()
       
   144 
       
   145     def refresh_args(self):
       
   146         rows = self.browser.list_function_args(self.oid)
       
   147         self._arguments = OrderedDict([(x['name'], Argument(self.browser, self, **x)) for x in rows])
       
   148 
       
   149     @property
       
   150     def arguments(self):
       
   151         if self._arguments is None:
       
   152             self.refresh_args()
       
   153         return self._arguments
   126 
   154 
   127     @property
   155     @property
   128     def definition(self):
   156     def definition(self):
   129         """Get full function definition including CREATE command."""
   157         """Get full function definition including CREATE command."""
   130         if not self._definition:
   158         if not self._definition:
   304     def list_functions(self, schema='public'):
   332     def list_functions(self, schema='public'):
   305         '''List functions in schema.'''
   333         '''List functions in schema.'''
   306         return self._query('''
   334         return self._query('''
   307             SELECT
   335             SELECT
   308                 p.oid as "oid",
   336                 p.oid as "oid",
   309                 p.proname as "name",
   337                 p.proname || '(' || array_to_string(
       
   338                     array(SELECT pg_catalog.format_type(unnest(p.proargtypes), NULL)),
       
   339                       ', '
       
   340                 ) || ')' as "name",
       
   341                 p.proname as "function_name",
   310                 pg_catalog.pg_get_function_result(p.oid) as "result",
   342                 pg_catalog.pg_get_function_result(p.oid) as "result",
   311                 pg_catalog.pg_get_function_arguments(p.oid) as "arguments",
       
   312                 p.prosrc as "source",
   343                 p.prosrc as "source",
   313                 CASE
   344                 CASE
   314                     WHEN p.proisagg THEN 'agg'
   345                     WHEN p.proisagg THEN 'agg'
   315                     WHEN p.proiswindow THEN 'window'
   346                     WHEN p.proiswindow THEN 'window'
   316                     WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
   347                     WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
   317                     ELSE 'normal'
   348                     ELSE 'normal'
   318                 END as "type"
   349                 END as "type"
   319             FROM pg_catalog.pg_proc p
   350             FROM pg_catalog.pg_proc p
   320             LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
   351             LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
   321             WHERE pg_catalog.pg_function_is_visible(p.oid)
   352             WHERE n.nspname = %s
   322                 AND n.nspname = %s
       
   323             ORDER BY 1, 2, 4;
   353             ORDER BY 1, 2, 4;
   324             ''', [schema])
   354             ''', [schema])
       
   355 
       
   356     def list_function_args(self, oid):
       
   357         """List function arguments.
       
   358 
       
   359         Notes about query:
       
   360             type: Use allargtypes if present, argtypes otherwise.
       
   361                 The trick with [0:999] moves lower bound from 0 to default 1
       
   362                 by slicing all elements (slices has always lower bound 1).
       
   363             mode: This trick makes array of NULLs of same length as argnames,
       
   364                 in case argmodes is NULL.
       
   365             default: Use pg_get_expr, split output by ', '
       
   366                 FIXME: will fail if ', ' is present in default value string.
       
   367         """
       
   368         return self._query('''
       
   369             SELECT
       
   370               unnest(p.proargnames) AS "name",
       
   371               pg_catalog.format_type(unnest(
       
   372                 COALESCE(p.proallargtypes, (p.proargtypes::oid[])[0:999])
       
   373               ), NULL) AS "type",
       
   374               unnest(
       
   375                 COALESCE(
       
   376                   p.proargmodes::text[],
       
   377                   array(SELECT NULL::text FROM generate_series(1, array_upper(p.proargnames, 1)))
       
   378                 )
       
   379               ) AS "mode",
       
   380               unnest(array_cat(
       
   381                 array_fill(NULL::text, array[COALESCE(array_upper(p.proargnames,1),0) - p.pronargdefaults]),
       
   382                 string_to_array(pg_get_expr(p.proargdefaults, 'pg_proc'::regclass, true), ', ')
       
   383               )) AS "default"
       
   384             FROM pg_proc p
       
   385             WHERE p.oid = %s''', [oid])
   325 
   386 
   326     def get_function_definition(self, oid):
   387     def get_function_definition(self, oid):
   327         """Get full function definition, including CREATE command etc.
   388         """Get full function definition, including CREATE command etc.
   328 
   389 
   329         Args:
   390         Args: