Skip to content

Commit 08d57b5

Browse files
committed
Created a connection#execute_procedure method that takes can take any number of ruby objects as variables and quotes them according to the connection's rules. Also added an ActiveRecord::Base class level core extension that hooks into this. It also checks if the connection responds to #execute_procedure and if not returns an empty array.
1 parent e67df49 commit 08d57b5

File tree

6 files changed

+64
-0
lines changed

6 files changed

+64
-0
lines changed

2000-2005-adapter.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
2929
"test/cases/column_test_sqlserver.rb",
3030
"test/cases/connection_test_sqlserver.rb",
3131
"test/cases/eager_association_test_sqlserver.rb",
32+
"test/cases/execute_procedure_test_sqlserver.rb",
3233
"test/cases/inheritance_test_sqlserver.rb",
3334
"test/cases/migration_test_sqlserver.rb",
3435
"test/cases/offset_and_limit_test_sqlserver.rb",

CHANGELOG

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11

22
MASTER
33

4+
* Created a connection#execute_procedure method that takes can take any number of ruby objects as variables
5+
and quotes them according to the connection's rules. Also added an ActiveRecord::Base class level core
6+
extension that hooks into this. It also checks if the connection responds to #execute_procedure and if
7+
not returns an empty array. [Ken Collins]
8+
49
* Added a #enable_default_unicode_types class attribute access to make all new added or changed string types
510
like :string/:text default to unicode/national data types. See the README for full details. Added a rake
611
task that assists setting this to true when running tests. [Ken Collins]

README.rdoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ The SQL Server adapter for rails is back for ActiveRecord 2.2 and up! We are cur
66

77
== What's New
88

9+
* An ActiveRecord::Base.execute_procedure method that can be used by classes.
910
* Enabled support for DDL transactions.
1011
* Micro second support. Time#usec is automatically converted to SQL Server's 3.33 millisecond limitation.
1112
* Datetime data types before type casting are represented correctly. For example: 1998-01-01 23:59:59.997
@@ -26,6 +27,13 @@ Both SQL Server 2000 and 2005 do not have native data types for just 'date' or '
2627

2728
This implementation has some limitations. To date we can only coerce date/time types for models that conform to the expected ActiveRecord class to table naming convention. So a table of 'foo_bar_widgets' will look for coerced types in the FooBarWidget class if it exists.
2829

30+
==== Executing Stored Procedures
31+
32+
Every class that sub classes ActiveRecord::Base will now have an execute_procedure class method to use. This method takes the name of the stored procedure which can be a string or symbol and any number of variables to pass to the procedure. Arguments will automatically be quoted per the connection's standards as normal. For example.
33+
34+
Account.execute_procedure :update_totals, 'admin', nil, true
35+
36+
2937
==== Native Data Type Support
3038

3139
Currently the following custom data types have been tested for schema definitions.

lib/active_record/connection_adapters/sqlserver_adapter.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,15 @@ def execute(sql, name = nil, &block)
334334
finish_statement_handle(handle)
335335
end
336336

337+
def execute_procedure(proc_name, *variables)
338+
holders = (1..variables.size).to_a.map{|n|'?'}.join(', ')
339+
statement = "EXEC #{proc_name} #{holders}".strip
340+
sql = statement.gsub('?') { quote(variables.shift) }
341+
select(sql,'PROCEDURE',true).inject([]) do |results,row|
342+
results << row.with_indifferent_access
343+
end
344+
end
345+
337346
def begin_db_transaction
338347
do_execute "BEGIN TRANSACTION"
339348
end

lib/core_ext/active_record.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ class << klass
1212

1313
module ClassMethods
1414

15+
def execute_procedure(proc_name, *variables)
16+
if connection.respond_to?(:execute_procedure)
17+
connection.execute_procedure(proc_name,*variables)
18+
else
19+
[]
20+
end
21+
end
22+
1523
def coerce_sqlserver_date(*attributes)
1624
write_inheritable_attribute :coerced_sqlserver_date_columns, Set.new(attributes.map(&:to_s))
1725
end
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
require 'cases/sqlserver_helper'
2+
3+
class ExecuteProcedureTestSqlserver < ActiveRecord::TestCase
4+
5+
def setup
6+
@klass = ActiveRecord::Base
7+
end
8+
9+
should 'execute a simple procedure' do
10+
tables = @klass.execute_procedure :sp_tables
11+
assert_instance_of Array, tables
12+
assert_instance_of HashWithIndifferentAccess, tables.first
13+
end
14+
15+
should 'take parameter arguments' do
16+
tables = @klass.execute_procedure :sp_tables, 'sql_server_chronics'
17+
table_info = tables.first
18+
assert_equal 1, tables.size
19+
assert_equal 'activerecord_unittest', table_info[:TABLE_QUALIFIER], "Table Info: #{table_info.inspect}"
20+
assert_equal 'TABLE', table_info[:TABLE_TYPE], "Table Info: #{table_info.inspect}"
21+
end
22+
23+
should 'quote bind vars correctly' do
24+
assert_sql(/EXEC sp_tables '%sql_server%', NULL, NULL, NULL, 1/) do
25+
@klass.execute_procedure :sp_tables, '%sql_server%', nil, nil, nil, true
26+
end if sqlserver_2005?
27+
assert_sql(/EXEC sp_tables '%sql_server%', NULL, NULL, NULL/) do
28+
@klass.execute_procedure :sp_tables, '%sql_server%', nil, nil, nil
29+
end if sqlserver_2000?
30+
end
31+
32+
33+
end

0 commit comments

Comments
 (0)