schema_plus_functions 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '09790e6271a884bb4cf768a7f75a25ef2cce002b91b9c2bc066f6992ea340cb0'
4
+ data.tar.gz: f87cde834a3236137bbcc1aa0be6f417c186c8d505ef0c6ed421c68fe4224c70
5
+ SHA512:
6
+ metadata.gz: 61e40e645fb97bc23908992339eefe32fd99574f6846e4d7cc5d27ab064e9eca14faacb1445901d3e91757a61a27e1ee1a5d34d99ad3e85cf1bf2e3503fdcb60
7
+ data.tar.gz: e355ac3b4266adbff2f1d97690e725818d124a8a1f00c9976df23c35a862a51c7df7c72482c4d1be3c456d7fade5f7b742ed7a84c4b01a15d25a5bbab568c9b4
@@ -0,0 +1,7 @@
1
+ /coverage
2
+ /tmp
3
+ /pkg
4
+ /Gemfile.local
5
+
6
+ *.lock
7
+ *.log
@@ -0,0 +1,16 @@
1
+ # This file was auto-generated by the schema_dev tool, based on the data in
2
+ # ./schema_dev.yml
3
+ # Please do not edit this file; any changes will be overwritten next time
4
+ # schema_dev gets run.
5
+ ---
6
+ sudo: false
7
+ rvm:
8
+ - 2.3.1
9
+ gemfile:
10
+ - gemfiles/activerecord-5.2/Gemfile.postgresql
11
+ env: POSTGRESQL_DB_USER=postgres
12
+ addons:
13
+ postgresql: '9.4'
14
+ before_script: bundle exec rake create_databases
15
+ after_script: bundle exec rake drop_databases
16
+ script: bundle exec rake travis
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gemspec
6
+
7
+ gemfile_local = File.expand_path '../Gemfile.local', __FILE__
8
+ eval File.read(gemfile_local), binding, gemfile_local if File.exist? gemfile_local
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2020 Edward Rudd
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,142 @@
1
+ [![Gem Version](https://badge.fury.io/rb/schema_plus_functions.svg)](http://badge.fury.io/rb/schema_plus_functions)
2
+ [![Build Status](https://secure.travis-ci.org/SchemaPlus/schema_plus_functions.svg)](http://travis-ci.org/SchemaPlus/schema_plus_functions)
3
+ [![Coverage Status](https://img.shields.io/coveralls/SchemaPlus/schema_plus_functions.svg)](https://coveralls.io/r/SchemaPlus/schema_plus_functions)
4
+ [![Dependency Status](https://gemnasium.com/SchemaPlus/schema_plus_functions.svg)](https://gemnasium.com/SchemaPlus/schema_plus_functions)
5
+
6
+ # SchemaPlus::Functions
7
+
8
+ SchemaPlus::Functions adds support for SQL functions in ActiveRecord.
9
+
10
+ SchemaPlus::Functions is part of the [SchemaPlus](https://github.com/SchemaPlus/) family of Ruby on Rails ActiveRecord extension gems.
11
+
12
+ ## Installation
13
+
14
+ <!-- SCHEMA_DEV: TEMPLATE INSTALLATION - begin -->
15
+ <!-- These lines are auto-inserted from a schema_dev template -->
16
+ As usual:
17
+
18
+ ```ruby
19
+ gem "schema_plus_functions" # in a Gemfile
20
+ gem.add_dependency "schema_plus_functions" # in a .gemspec
21
+ ```
22
+
23
+ <!-- SCHEMA_DEV: TEMPLATE INSTALLATION - end -->
24
+
25
+ ## Usage
26
+
27
+ ### Migrations
28
+
29
+ To declare a function use `create_function`:
30
+
31
+ create_function :test, "start date, stop date DEFAULT NULL::date", <<-END
32
+ RETURNS integer
33
+ LANGUAGE plpgsql
34
+ AS $$
35
+ DECLARE
36
+ processed INTEGER = 0;
37
+ BEGIN
38
+ processed = processed + 1;
39
+ RETURN processed;
40
+ END;
41
+ $$
42
+ END
43
+
44
+ To create an aggregate function specify the `function_type`:
45
+
46
+ create_function :array_cat_agg, "anyarray", <<-END, function_type: :aggregate
47
+ (SFUNC=array_cat,STYPE=anyarray)
48
+ END
49
+
50
+ To update a function in a new migration specify the `allow_replace` property
51
+
52
+ create_function :test, "start date, stop date DEFAULT NULL::date", <<-END, allow_replace: true
53
+ RETURNS integer
54
+ LANGUAGE plpgsql
55
+ AS $$
56
+ DECLARE
57
+ processed INTEGER = 0;
58
+ BEGIN
59
+ processed = processed + 5;
60
+ RETURN processed;
61
+ END;
62
+ $$
63
+ END
64
+
65
+ To remove a function use `drop_function` with the name and argument types:
66
+
67
+ drop_function :test, "start date, stop date"
68
+
69
+ To remove an aggregate use `drop_function` with the name and argument types with the `function_type`:
70
+
71
+ drop_function :array_cat_agg, "anyarray", function_type: :aggrgate
72
+
73
+ ### Introspection
74
+
75
+ You can query the list of user functions at the connection level (uncached):
76
+
77
+ connection.functions
78
+
79
+ This will return a array of arrays. The inner array containing the function_name, argument types
80
+ and possible function type.
81
+
82
+ ## Compatibility
83
+
84
+ SchemaPlus::Functions is tested on:
85
+
86
+ <!-- SCHEMA_DEV: MATRIX - begin -->
87
+ <!-- These lines are auto-generated by schema_dev based on schema_dev.yml -->
88
+ * ruby **2.3.1** with activerecord **5.2**, using **postgresql**
89
+
90
+ <!-- SCHEMA_DEV: MATRIX - end -->
91
+
92
+ ## History
93
+
94
+ * 0.1.0 - Initial release
95
+
96
+ ## Development & Testing
97
+
98
+ Are you interested in contributing to SchemaPlus::Functions? Thanks! Please follow
99
+ the standard protocol: fork, feature branch, develop, push, and issue pull
100
+ request.
101
+
102
+ Some things to know about to help you develop and test:
103
+
104
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - begin -->
105
+ <!-- These lines are auto-inserted from a schema_dev template -->
106
+ * **schema_dev**: SchemaPlus::Functions uses [schema_dev](https://github.com/SchemaPlus/schema_dev) to
107
+ facilitate running rspec tests on the matrix of ruby, activerecord, and database
108
+ versions that the gem supports, both locally and on
109
+ [travis-ci](http://travis-ci.org/SchemaPlus/schema_plus_functions)
110
+
111
+ To to run rspec locally on the full matrix, do:
112
+
113
+ $ schema_dev bundle install
114
+ $ schema_dev rspec
115
+
116
+ You can also run on just one configuration at a time; For info, see `schema_dev --help` or the [schema_dev](https://github.com/SchemaPlus/schema_dev) README.
117
+
118
+ The matrix of configurations is specified in `schema_dev.yml` in
119
+ the project root.
120
+
121
+
122
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - end -->
123
+
124
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - begin -->
125
+ <!-- These lines are auto-inserted from a schema_dev template -->
126
+ * **schema_plus_core**: SchemaPlus::Functions uses the SchemaPlus::Core API that
127
+ provides middleware callback stacks to make it easy to extend
128
+ ActiveRecord's behavior. If that API is missing something you need for
129
+ your contribution, please head over to
130
+ [schema_plus_core](https://github.com/SchemaPlus/schema_plus_core) and open
131
+ an issue or pull request.
132
+
133
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - end -->
134
+
135
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - begin -->
136
+ <!-- These lines are auto-inserted from a schema_dev template -->
137
+ * **schema_monkey**: SchemaPlus::Functions is implemented as a
138
+ [schema_monkey](https://github.com/SchemaPlus/schema_monkey) client,
139
+ using [schema_monkey](https://github.com/SchemaPlus/schema_monkey)'s
140
+ convention-based protocols for extending ActiveRecord and using middleware stacks.
141
+
142
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - end -->
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'schema_dev/tasks'
7
+
8
+ task :default => :spec
9
+
10
+ require 'rspec/core/rake_task'
11
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => File.expand_path('..', __FILE__)
3
+
4
+ File.exist?(gemfile_local = File.expand_path('../Gemfile.local', __FILE__)) and eval File.read(gemfile_local), binding, gemfile_local
@@ -0,0 +1,3 @@
1
+ eval File.read File.expand_path('../../Gemfile.base', __FILE__)
2
+
3
+ gem "activerecord", ">= 5.2.0.beta0", "< 5.3"
@@ -0,0 +1,10 @@
1
+ require "pathname"
2
+ eval(Pathname.new(__FILE__).dirname.join("Gemfile.base").read, binding)
3
+
4
+ platform :ruby do
5
+ gem "pg"
6
+ end
7
+
8
+ platform :jruby do
9
+ gem 'activerecord-jdbcpostgresql-adapter'
10
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'schema_plus/core'
4
+
5
+ require_relative 'functions/version'
6
+ require_relative 'functions/active_record/connection_adapters/abstract_adapter'
7
+ require_relative 'functions/active_record/migration/command_recorder'
8
+ require_relative 'functions/middleware'
9
+
10
+ module SchemaPlus::Functions
11
+ module ActiveRecord
12
+ module ConnectionAdapters
13
+ autoload :PostgresqlAdapter, 'schema_plus/functions/active_record/connection_adapters/postgresql_adapter'
14
+ end
15
+ end
16
+ end
17
+
18
+ SchemaMonkey.register SchemaPlus::Functions
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SchemaPlus::Functions
4
+ module ActiveRecord
5
+ module ConnectionAdapters
6
+ module AbstractAdapter
7
+ # Create a function. Valid options are :force,
8
+ # :allow_replace, and :function_type
9
+ def create_function(function_name, params, definition, options = {})
10
+ SchemaMonkey::Middleware::Migration::CreateFunction.start(connection: self, function_name: function_name, params: params, definition: definition, options: options) do |env|
11
+ function_name = env.function_name
12
+ function_type = (options[:function_type] || :function).to_s.upcase
13
+ params = env.params
14
+ definition = env.definition
15
+ options = env.options
16
+
17
+ definition = definition.to_sql if definition.respond_to? :to_sql
18
+ if options[:force]
19
+ drop_function(function_name, params, function_type: options[:function_type], if_exists: true)
20
+ end
21
+
22
+ command = if options[:allow_replace]
23
+ "CREATE OR REPLACE"
24
+ else
25
+ "CREATE"
26
+ end
27
+ execute "#{command} #{function_type} #{function_name}(#{params}) #{definition}"
28
+ end
29
+ end
30
+
31
+ # Remove a function. Valid options are :function_type,
32
+ # :if_exists, and :cascade
33
+ #
34
+ # If your function type is an aggregate, you must specify the type
35
+ #
36
+ # drop_function 'my_func', 'int', if_exists: true, cascade: true
37
+ # drop_function 'my_agg', 'int', function_type: :aggregate
38
+ def drop_function(function_name, params, options = {})
39
+ SchemaMonkey::Middleware::Migration::CreateFunction.start(connection: self, function_name: function_name, params: params, options: options) do |env|
40
+ function_name = env.function_name
41
+ params = env.params
42
+ options = env.options
43
+ function_type = (options[:function_type] || :function).to_s.upcase
44
+
45
+ sql = "DROP #{function_type}"
46
+ sql += " IF EXISTS" if options[:if_exists]
47
+ sql += " #{function_name}(#{params})"
48
+ sql += " CASCADE" if options[:cascade]
49
+
50
+ execute sql
51
+ end
52
+ end
53
+
54
+ #####################################################################
55
+ #
56
+ # The functions below here are abstract; each subclass should
57
+ # define them all. Defining them here only for reference.
58
+ #
59
+
60
+ # (abstract) Return the Function objects for functions
61
+ def functions(name = nil)
62
+ raise "Internal Error: Connection adapter did not override abstract function"
63
+ end
64
+
65
+ # (abstract) Return the Function definition for the named function and parameter set
66
+ def function_definition(function_name, params, name = nil)
67
+ raise "Internal Error: Connection adapter did not override abstract function"
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,75 @@
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,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SchemaPlus::Functions
4
+ module ActiveRecord
5
+ module Migration
6
+ module CommandRecorder
7
+ def create_function(*args, &block)
8
+ record(:create_function, args, &block)
9
+ end
10
+
11
+ def drop_function(*args, &block)
12
+ record(:drop_function, args, &block)
13
+ end
14
+
15
+ def invert_create_function(args)
16
+ options = {}
17
+ options[:function_type] = args[3][:function_type] if args[3].has_key?(:function_type)
18
+ [:drop_function, [args.first, args.second, options]]
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SchemaPlus::Functions
4
+ module Middleware
5
+ module Dumper
6
+ module Tables
7
+ # Dump
8
+ def after(env)
9
+ env.connection.functions.each do |(function_name, params, _options)|
10
+ full_params, definition, function_type = env.connection.function_definition(function_name, params)
11
+ heredelim = "END_FUNCTION_#{function_name.upcase}"
12
+ extra_options = ", function_type: :#{function_type}" if function_type.present?
13
+ statement = <<~ENDFUNCTION
14
+ create_function "#{function_name}", "#{full_params}", <<-'#{heredelim}', :force => true#{extra_options}
15
+ #{definition}
16
+ #{heredelim}
17
+ ENDFUNCTION
18
+
19
+ env.dump.final << statement
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ module Schema
26
+ module Functions
27
+ ENV = [:connection, :query_name, :functions]
28
+ end
29
+
30
+ module FunctionDefinition
31
+ ENV = [:connection, :function_name, :params, :query_name, :definition, :function_type]
32
+ end
33
+ end
34
+
35
+ module Migration
36
+ module CreateFunction
37
+ ENV = [:connection, :function_name, :params, :definition, :options]
38
+ end
39
+
40
+ module DropFunction
41
+ ENV = [:connection, :function_name, :params, :options]
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SchemaPlus
4
+ module Functions
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'schema_plus/functions'
@@ -0,0 +1,6 @@
1
+ ruby:
2
+ - 2.3.1
3
+ activerecord:
4
+ - 5.2
5
+ db:
6
+ - postgresql
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'schema_plus/functions/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = "schema_plus_functions"
9
+ gem.version = SchemaPlus::Functions::VERSION
10
+ gem.authors = ["Edward Rudd"]
11
+ gem.email = ["urkle@outoforder.cc"]
12
+ gem.summary = %q{Adds support for functions in ActiveRecord}
13
+ gem.description = %q{Adds support for functions in ActiveRecord}
14
+ gem.homepage = "https://github.com/SchemaPlus/schema_plus_functions"
15
+ gem.license = "MIT"
16
+
17
+ gem.files = `git ls-files -z`.split("\x0")
18
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.require_paths = ["lib"]
21
+
22
+ gem.add_dependency "activerecord", ">= 5.2", "< 5.3"
23
+ gem.add_dependency "schema_plus_core"
24
+
25
+ gem.add_development_dependency "bundler"
26
+ gem.add_development_dependency "rake", "~> 10.0"
27
+ gem.add_development_dependency "rspec", "~> 3.0"
28
+ gem.add_development_dependency "schema_dev", "~> 3.11", ">= 3.11.1"
29
+ gem.add_development_dependency "simplecov"
30
+ gem.add_development_dependency "simplecov-gem-profile"
31
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ActiveRecord::Migration do
6
+ it "creates the function definition for an aggregate function" do
7
+ apply_migration do
8
+ create_function :array_cat_agg, "anyarray", <<-END, function_type: :aggregate
9
+ (SFUNC=array_cat,STYPE=anyarray)
10
+ END
11
+ end
12
+
13
+ expect(functions).to include(['array_cat_agg', 'anyarray', {function_type: :aggregate}])
14
+ end
15
+
16
+ it "creates the function definition for a regular function" do
17
+ apply_migration do
18
+ create_function :test, "start date, stop date DEFAULT NULL::date", <<-END
19
+ RETURNS integer
20
+ LANGUAGE plpgsql
21
+ AS $$
22
+ DECLARE
23
+ processed INTEGER = 0;
24
+ BEGIN
25
+ processed = processed + 1;
26
+ RETURN processed;
27
+ END;
28
+ $$
29
+ END
30
+ end
31
+
32
+ expect(functions).to include(['test', 'start date, stop date', {}])
33
+ end
34
+
35
+ protected
36
+
37
+ def functions
38
+ ActiveRecord::Base.connection.functions
39
+ end
40
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'stringio'
5
+
6
+ describe "Schema dump" do
7
+ it "includes the function definition for an aggregate function" do
8
+ apply_migration do
9
+ create_function :array_cat_agg, "anyarray", <<-END, function_type: :aggregate
10
+ (SFUNC=array_cat,STYPE=anyarray)
11
+ END
12
+ end
13
+
14
+ expect(dump_schema).to match(%r{create_function.+array_cat_agg.+aggregate})
15
+ end
16
+
17
+ it "includes the function definition for a regular function" do
18
+ apply_migration do
19
+ create_function :test, "start date, stop date DEFAULT NULL::date", <<-END
20
+ RETURNS integer
21
+ LANGUAGE plpgsql
22
+ AS $$
23
+ DECLARE
24
+ processed INTEGER = 0;
25
+ BEGIN
26
+ processed = processed + 1;
27
+ RETURN processed;
28
+ END;
29
+ $$
30
+ END
31
+ end
32
+
33
+ expect(dump_schema).to match(%r{create_function.+test.+start date, stop date DEFAULT})
34
+ end
35
+
36
+ protected
37
+
38
+ def dump_schema(opts = {})
39
+ stream = StringIO.new
40
+
41
+ ActiveRecord::SchemaDumper.ignore_tables = Array.wrap(opts[:ignore]) || []
42
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
43
+
44
+ stream.string
45
+ end
46
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'simplecov'
4
+ require 'simplecov-gem-profile'
5
+ SimpleCov.start "gem"
6
+
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
+
10
+ require 'rspec'
11
+ require 'active_record'
12
+ require 'schema_plus_functions'
13
+ require 'schema_dev/rspec'
14
+
15
+ SchemaDev::Rspec.setup
16
+
17
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
18
+
19
+ RSpec.configure do |config|
20
+ config.warnings = true
21
+ config.around(:each) do |example|
22
+ ActiveRecord::Migration.suppress_messages do
23
+ begin
24
+ example.run
25
+ ensure
26
+ ActiveRecord::Base.connection.functions.each do |(func_name, params, options)|
27
+ ActiveRecord::Migration.drop_function func_name, params, options
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ def define_schema(config = {}, &block)
35
+ ActiveRecord::Migration.suppress_messages do
36
+ ActiveRecord::Schema.define do
37
+ ActiveRecord::Base.connection.functions.each do |(func_name, params, options)|
38
+ ActiveRecord::Migration.drop_function func_name, params, options
39
+ end
40
+ instance_eval &block
41
+ end
42
+ end
43
+ end
44
+
45
+ def apply_migration(config = {}, &block)
46
+ ActiveRecord::Schema.define do
47
+ instance_eval &block
48
+ end
49
+ end
50
+
51
+ SimpleCov.command_name "[ruby#{RUBY_VERSION}-activerecord#{::ActiveRecord.version}-#{ActiveRecord::Base.connection.adapter_name}]"
metadata ADDED
@@ -0,0 +1,191 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: schema_plus_functions
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Edward Rudd
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-08-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.3'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '5.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.3'
33
+ - !ruby/object:Gem::Dependency
34
+ name: schema_plus_core
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '10.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '10.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: schema_dev
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '3.11'
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: 3.11.1
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: '3.11'
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: 3.11.1
109
+ - !ruby/object:Gem::Dependency
110
+ name: simplecov
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ - !ruby/object:Gem::Dependency
124
+ name: simplecov-gem-profile
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ description: Adds support for functions in ActiveRecord
138
+ email:
139
+ - urkle@outoforder.cc
140
+ executables: []
141
+ extensions: []
142
+ extra_rdoc_files: []
143
+ files:
144
+ - ".gitignore"
145
+ - ".travis.yml"
146
+ - Gemfile
147
+ - LICENSE.txt
148
+ - README.md
149
+ - Rakefile
150
+ - gemfiles/Gemfile.base
151
+ - gemfiles/activerecord-5.2/Gemfile.base
152
+ - gemfiles/activerecord-5.2/Gemfile.postgresql
153
+ - lib/schema_plus/functions.rb
154
+ - lib/schema_plus/functions/active_record/connection_adapters/abstract_adapter.rb
155
+ - lib/schema_plus/functions/active_record/connection_adapters/postgresql_adapter.rb
156
+ - lib/schema_plus/functions/active_record/migration/command_recorder.rb
157
+ - lib/schema_plus/functions/middleware.rb
158
+ - lib/schema_plus/functions/version.rb
159
+ - lib/schema_plus_functions.rb
160
+ - schema_dev.yml
161
+ - schema_plus_functions.gemspec
162
+ - spec/migration_spec.rb
163
+ - spec/schema_dumper_spec.rb
164
+ - spec/spec_helper.rb
165
+ homepage: https://github.com/SchemaPlus/schema_plus_functions
166
+ licenses:
167
+ - MIT
168
+ metadata: {}
169
+ post_install_message:
170
+ rdoc_options: []
171
+ require_paths:
172
+ - lib
173
+ required_ruby_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ requirements: []
184
+ rubygems_version: 3.0.6
185
+ signing_key:
186
+ specification_version: 4
187
+ summary: Adds support for functions in ActiveRecord
188
+ test_files:
189
+ - spec/migration_spec.rb
190
+ - spec/schema_dumper_spec.rb
191
+ - spec/spec_helper.rb