procbuddy 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +2 -0
- data/README +46 -0
- data/Rakefile +14 -0
- data/lib/procbuddy/connection_adapters/abstract/schema_definitions.rb +14 -0
- data/lib/procbuddy/connection_adapters/abstract/schema_statements.rb +29 -0
- data/lib/procbuddy/connection_adapters/abstract_adapter.rb +20 -0
- data/lib/procbuddy/connection_adapters/mysql_adapter.rb +35 -0
- data/lib/procbuddy/connection_adapters/sqlserver_adapter.rb +36 -0
- data/lib/procbuddy/schema_dumper.rb +66 -0
- data/lib/procbuddy/version.rb +9 -0
- data/lib/procbuddy.rb +55 -0
- metadata +79 -0
data/CHANGELOG
ADDED
data/README
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
== Rails SQL Procs
|
2
|
+
|
3
|
+
Library which adds SQL Stored Procedures to Rails. Adds create_proc and drop_proc to the ActiveRecord::ConnectionAdapters::AbstractAdapter (which makes them available to migrations) and adds support for dumping procs in the ActiveRecord::SchemaDumper.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
To install:
|
8
|
+
|
9
|
+
gem install procbuddy
|
10
|
+
|
11
|
+
Then add the following to your Rails config/environment.rb:
|
12
|
+
|
13
|
+
require_gem 'procbuddy'
|
14
|
+
require 'procbuddy'
|
15
|
+
|
16
|
+
== Usage
|
17
|
+
|
18
|
+
You can then use create_proc and drop_proc in your migrations. For example:
|
19
|
+
|
20
|
+
class CreateLameProc < ActiveRecord::Migration
|
21
|
+
def self.up
|
22
|
+
create_proc :lameness, <<EOSQL
|
23
|
+
SELECT 1 + 1 as lame
|
24
|
+
EOSQL
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.down
|
28
|
+
drop_proc :lameness
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
This extension also adds support for procs in the ActiveRecord::SchemaDumper class.
|
33
|
+
|
34
|
+
The following drivers are supported:
|
35
|
+
|
36
|
+
SQL Server
|
37
|
+
|
38
|
+
== Known Issues
|
39
|
+
|
40
|
+
* Drivers not mentioned above are not supported.
|
41
|
+
|
42
|
+
If you find any issues please send an email to stewbawka@gmail.com .
|
43
|
+
|
44
|
+
== Contributing
|
45
|
+
|
46
|
+
If you would like to implement stored procedure support for other adapters then please drop me an email. Better yet, write up the adapter modifications and send them to me. :-)
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gemspec|
|
4
|
+
gemspec.name = "procbuddy"
|
5
|
+
gemspec.summary = "sql stored procedures in migrations"
|
6
|
+
gemspec.description = "Provide create_proc and drop_proc in migrations. Also extends SchemaDumper to clue in about procs"
|
7
|
+
gemspec.email = "stewbawka@gmail.com"
|
8
|
+
gemspec.homepage = "http://blog.stewbawka.com""
|
9
|
+
gemspec.authors = ["Stuart Wade"]
|
10
|
+
end
|
11
|
+
Jeweler::GemcutterTasks.new
|
12
|
+
rescue LoadError
|
13
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
|
14
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Procbuddy
|
2
|
+
module ConnectionAdapters # :nodoc:
|
3
|
+
module SchemaStatements
|
4
|
+
# Create a proc.
|
5
|
+
def create_proc(name, sql, options={})
|
6
|
+
if supports_procs?
|
7
|
+
proc_definition = ProcDefinition.new(self, name, sql)
|
8
|
+
|
9
|
+
if options[:force]
|
10
|
+
drop_proc(name) rescue nil
|
11
|
+
end
|
12
|
+
|
13
|
+
create_sql = "CREATE PROCEDURE "
|
14
|
+
create_sql << "#{name}"
|
15
|
+
create_sql << proc_definition.sql
|
16
|
+
execute create_sql
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Drop a proc.
|
21
|
+
def drop_proc(name, options={})
|
22
|
+
if supports_procs?
|
23
|
+
drop_sql = "DROP PROCEDURE #{name}"
|
24
|
+
execute drop_sql
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class AbstractAdapter
|
4
|
+
# Subclasses should override and return true if they support triggers.
|
5
|
+
def supports_procs?
|
6
|
+
return false
|
7
|
+
end
|
8
|
+
|
9
|
+
# Get a list of all triggers for the current database
|
10
|
+
def procs(name = nil)
|
11
|
+
raise NotImplementedError, "procs is an abstract method"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Get the code for the specified trigger
|
15
|
+
def proc_code(proc, name=nil)
|
16
|
+
raise NotImplementedError, "proc_code is an abstract method"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class MysqlAdapter
|
4
|
+
# Returns true as this adapter supports views.
|
5
|
+
def supports_views?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def tables(name = nil) #:nodoc:
|
10
|
+
tables = []
|
11
|
+
execute("SHOW TABLE STATUS", name).each { |row| tables << row[0] if row[17] != 'VIEW' }
|
12
|
+
tables
|
13
|
+
end
|
14
|
+
|
15
|
+
def views(name = nil) #:nodoc:
|
16
|
+
views = []
|
17
|
+
execute("SHOW TABLE STATUS", name).each { |row| views << row[0] if row[17] == 'VIEW' }
|
18
|
+
views
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get the view select statement for the specified table.
|
22
|
+
def view_select_statement(view, name=nil)
|
23
|
+
row = execute("SHOW CREATE VIEW #{view}", name).each do |row|
|
24
|
+
return convert_statement(row[1]) if row[0] == view
|
25
|
+
end
|
26
|
+
raise "No view called #{view} found"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def convert_statement(s)
|
31
|
+
s.gsub!(/.* AS (select .*)/, '\1')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class SQLServerAdapter
|
4
|
+
# Returns true as this adapter supports views.
|
5
|
+
def supports_procs?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
# Returns all the trigger names from the currently connected schema.
|
10
|
+
def procs(name = nil)
|
11
|
+
select_values("SELECT name FROM sysobjects WHERE type = 'P'", name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def proc_sp_helptext(proc, name=nil)
|
15
|
+
q =<<-ENDSQL
|
16
|
+
SELECT OBJECT_DEFINITION(OBJECT_ID('#{trigger}'));
|
17
|
+
ENDSQL
|
18
|
+
|
19
|
+
proc_def = select_value(q, name)
|
20
|
+
|
21
|
+
if !proc_def.blank?
|
22
|
+
return proc_def
|
23
|
+
else
|
24
|
+
raise "No proc called #{proc} found"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def proc_code(proc, name=nil)
|
30
|
+
proc_def = proc_sp_helptext(proc, name)
|
31
|
+
proc_def.sub(/^CREATE PROCEDURE \w+\s+/, '')
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class SchemaDumper
|
3
|
+
|
4
|
+
# A list of triggers which should not be dumped to the schema.
|
5
|
+
# Acceptable values are strings as well as regexp.
|
6
|
+
# This setting is only used if ActiveRecord::Base.schema_format == :ruby
|
7
|
+
cattr_accessor :ignore_procs
|
8
|
+
@@ignore_procs = []
|
9
|
+
|
10
|
+
def trailer_with_procs(stream)
|
11
|
+
# do nothing...we'll call this later
|
12
|
+
end
|
13
|
+
alias_method_chain :trailer, :triggers
|
14
|
+
|
15
|
+
# Add procs to the end of the dump stream
|
16
|
+
def dump_with_procs(stream)
|
17
|
+
dump_without_procs(stream)
|
18
|
+
begin
|
19
|
+
if @connection.supports_procs?
|
20
|
+
procs(stream)
|
21
|
+
end
|
22
|
+
rescue => e
|
23
|
+
ActiveRecord::Base.logger.error "Unable to dump procs: #{e}"
|
24
|
+
end
|
25
|
+
trailer_without_procs(stream)
|
26
|
+
stream
|
27
|
+
end
|
28
|
+
alias_method_chain :dump, :procs
|
29
|
+
|
30
|
+
# Add procs to the stream
|
31
|
+
def procs(stream)
|
32
|
+
@connection.procs.sort.each do |t|
|
33
|
+
next if ["schema_info", ignore_procs].flatten.any? do |ignored|
|
34
|
+
case ignored
|
35
|
+
when String: t == ignored
|
36
|
+
when Regexp: t =~ ignored
|
37
|
+
else
|
38
|
+
raise StandardError, 'ActiveRecord::SchemaDumper.ignore_procs accepts an array of String and / or Regexp values.'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
proc(t, stream)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Add the specified proc to the stream
|
46
|
+
def proc(proc, stream)
|
47
|
+
begin
|
48
|
+
t = StringIO.new
|
49
|
+
t.print " proc_code = <<EOSQL\n"
|
50
|
+
t.print @connection.proc_code(proc)
|
51
|
+
t.print "EOSQL\n"
|
52
|
+
t.print " create_proc(#{proc.to_sym.inspect}, "
|
53
|
+
t.print "proc_code, "
|
54
|
+
t.print ":force => true)\n"
|
55
|
+
t.rewind
|
56
|
+
stream.print t.read
|
57
|
+
rescue => e
|
58
|
+
stream.puts "# Could not dump proc #{proc.inspect} because of following #{e.class}"
|
59
|
+
stream.puts "# #{e.message}"
|
60
|
+
stream.puts "# #{e.trace}"
|
61
|
+
end
|
62
|
+
|
63
|
+
stream
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/procbuddy.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Procbuddy is based the rails_sql_views gem developped by Anthony Eden
|
2
|
+
# I have included his original copyright notice since this gem is derivative of his work.
|
3
|
+
#
|
4
|
+
#--
|
5
|
+
# Copyright (c) 2006 Anthony Eden
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
8
|
+
# a copy of this software and associated documentation files (the
|
9
|
+
# "Software"), to deal in the Software without restriction, including
|
10
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
11
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
12
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
13
|
+
# the following conditions:
|
14
|
+
#
|
15
|
+
# The above copyright notice and this permission notice shall be
|
16
|
+
# included in all copies or substantial portions of the Software.
|
17
|
+
#
|
18
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
20
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
22
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
23
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
24
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
#++
|
26
|
+
|
27
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
28
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
29
|
+
|
30
|
+
require 'rubygems'
|
31
|
+
|
32
|
+
#unless Kernel.respond_to?(:gem)
|
33
|
+
# Kernel.send :alias_method, :gem, :require_gem
|
34
|
+
#end
|
35
|
+
|
36
|
+
unless defined?(ActiveRecord)
|
37
|
+
begin
|
38
|
+
$:.unshift(File.dirname(__FILE__) + "/../../activerecord/lib")
|
39
|
+
require 'active_record'
|
40
|
+
rescue LoadError
|
41
|
+
gem 'activerecord'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#require 'core_ext/module'
|
46
|
+
|
47
|
+
require 'procbuddy/connection_adapters/abstract/schema_definitions'
|
48
|
+
require 'procbuddy/connection_adapters/abstract/schema_statements'
|
49
|
+
#require 'procbuddy/connection_adapters/mysql_adapter'
|
50
|
+
require 'procbuddy/connection_adapters/sqlserver_adapter'
|
51
|
+
require 'procbuddy/schema_dumper'
|
52
|
+
|
53
|
+
class ActiveRecord::ConnectionAdapters::AbstractAdapter
|
54
|
+
include Procbuddy::ConnectionAdapters::SchemaStatements
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: procbuddy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Stuart Wade
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-08-11 00:00:00 -03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Provide create_proc and drop_proc in migrations. Also extends SchemaDumper to clue in about stored procedures
|
23
|
+
email: stewbawka@gmail.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- lib/procbuddy/version.rb
|
32
|
+
- lib/procbuddy/schema_dumper.rb
|
33
|
+
- lib/procbuddy/connection_adapters/mysql_adapter.rb
|
34
|
+
- lib/procbuddy/connection_adapters/sqlserver_adapter.rb
|
35
|
+
- lib/procbuddy/connection_adapters/abstract_adapter.rb
|
36
|
+
- lib/procbuddy/connection_adapters/abstract/schema_statements.rb
|
37
|
+
- lib/procbuddy/connection_adapters/abstract/schema_definitions.rb
|
38
|
+
- lib/procbuddy.rb
|
39
|
+
- CHANGELOG
|
40
|
+
- Rakefile
|
41
|
+
- README
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://blog.stewbawka.com
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
hash: 19
|
66
|
+
segments:
|
67
|
+
- 1
|
68
|
+
- 3
|
69
|
+
- 4
|
70
|
+
version: 1.3.4
|
71
|
+
requirements: []
|
72
|
+
|
73
|
+
rubyforge_project: procbuddy
|
74
|
+
rubygems_version: 1.5.3
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: sql stored procedures in migrations
|
78
|
+
test_files: []
|
79
|
+
|