|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +module SchemaPlus::Functions |
| 4 | + module ActiveRecord |
| 5 | + module ConnectionAdapters |
| 6 | + module PostgresqlAdapter |
| 7 | + def drop_function(function_name, params, options = {}) |
| 8 | + clean_params = params.gsub(/ DEFAULT[^,]+/i, '') |
| 9 | + super(function_name, clean_params, options) |
| 10 | + end |
| 11 | + |
| 12 | + def functions(name = nil) #:nodoc: |
| 13 | + SchemaMonkey::Middleware::Schema::Functions.start(connection: self, query_name: name, functions: []) do |env| |
| 14 | + sql = <<-SQL |
| 15 | + SELECT P.proname as function_name, pg_get_function_identity_arguments(P.oid), proisagg as is_agg |
| 16 | + FROM pg_proc P |
| 17 | + WHERE |
| 18 | + pronamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false))) |
| 19 | + AND NOT EXISTS (SELECT 1 FROM pg_depend WHERE classid = 'pg_proc'::regclass |
| 20 | + AND objid = p.oid AND deptype = 'i') |
| 21 | + AND NOT EXISTS (SELECT 1 FROM pg_depend WHERE classid = 'pg_proc'::regclass |
| 22 | + AND objid = p.oid AND refclassid = 'pg_extension'::regclass AND deptype = 'e') |
| 23 | + ORDER BY 1,2 |
| 24 | + SQL |
| 25 | + |
| 26 | + env.functions += env.connection.query(sql, env.query_name).map do |row| |
| 27 | + options = {} |
| 28 | + options[:function_type] = :aggregate if row[2] |
| 29 | + [row[0], row[1], options] |
| 30 | + end |
| 31 | + end.functions |
| 32 | + end |
| 33 | + |
| 34 | + def function_definition(function_name, params, name = nil) #:nodoc: |
| 35 | + data = SchemaMonkey::Middleware::Schema::FunctionDefinition.start(connection: self, function_name: function_name, params: params, query_name: name) do |env| |
| 36 | + result = env.connection.query(<<-SQL, env.query_name) |
| 37 | + SELECT prosrc, |
| 38 | + pg_get_function_arguments(p.oid), |
| 39 | + pg_catalog.pg_get_function_result(p.oid) AS funcresult, |
| 40 | + (SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname, |
| 41 | + a.aggtransfn as transfn, |
| 42 | + format_type(a.aggtranstype, null) as transtype |
| 43 | + FROM pg_proc p |
| 44 | + LEFT JOIN pg_aggregate a ON a.aggfnoid = p.oid |
| 45 | + WHERE |
| 46 | + pronamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false))) |
| 47 | + AND proname = '#{quote_string(function_name)}' |
| 48 | + AND pg_get_function_identity_arguments(P.oid) = '#{quote_string(params)}' |
| 49 | + SQL |
| 50 | + |
| 51 | + row = result.first |
| 52 | + |
| 53 | + function_type = nil |
| 54 | + |
| 55 | + unless row.nil? |
| 56 | + sql = if row[4].present? || row[0] == 'aggregate_dummy' |
| 57 | + # it's an aggregate function |
| 58 | + function_type = :aggregate |
| 59 | + "(SFUNC=#{row[4]},STYPE=#{row[5]})" |
| 60 | + else |
| 61 | + "RETURNS #{row[2]} LANGUAGE #{row[3]} AS $$#{row[0]}$$" |
| 62 | + end |
| 63 | + env.params = row[1] |
| 64 | + env.definition = sql |
| 65 | + env.function_type = function_type |
| 66 | + end |
| 67 | + end |
| 68 | + |
| 69 | + return data.params, data.definition, data.function_type |
| 70 | + end |
| 71 | + end |
| 72 | + end |
| 73 | + end |
| 74 | +end |
| 75 | + |
0 commit comments