minus5_mssql 0.1.0 → 0.2.0

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.
@@ -53,26 +53,71 @@ module Minus5
53
53
 
54
54
  # Returns results first column of the first row.
55
55
  def select_value(sql)
56
- rows = execute(sql).each
57
- return nil if rows.size == 0
58
- row = rows[0]
59
- row[row.keys[0]]
56
+ rows = execute(sql).each(:as=>:array)
57
+ return if rows.size == 0
58
+ rows[0][0].kind_of?(Array) ? rows[0][0][0] : rows[0][0]
59
+ end
60
+
61
+ # Returns array of the values from the first column of all returned rows
62
+ def select_values(sql)
63
+ rows = execute(sql).each(:as=>:array)
64
+ return [] if rows.size == 0
65
+ (rows[0][0].kind_of?(Array) ? rows[0] : rows).map{|row| row[0] }
60
66
  end
61
67
 
62
- def select(sql)
63
- rows = execute(sql).each
64
- rows.size == 1 ? rows[0] : rows
68
+ def select(options)
69
+ if options.kind_of?(String)
70
+ execute(options).each(:symbolize_keys=>true)
71
+ else
72
+ options = {:primary_key=>:id}.merge(options)
73
+ results = execute(options[:sql]).each(:symbolize_keys=>true)
74
+ return [] if results.size == 0
75
+ return results if results[0].kind_of?(Hash)
76
+ data = {} #parent indexed by primary_key
77
+ results[0].each{ |row| data[row[options[:primary_key]]] = row }
78
+ options[:relations].each_with_index do |relation, index|index
79
+ result = results[index+1] #child result
80
+ result.each do |row|
81
+ #find parent row by foreign key and insert child row in collection
82
+ data_row = data[row[relation[:foreign_key]]]
83
+ next unless data_row
84
+ if relation[:type] == :one_to_many
85
+ data_row[relation[:name]] = [] unless data_row[relation[:name]]
86
+ data_row[relation[:name]] << row
87
+ elsif relation[:type] == :one_to_one
88
+ #merge child row with parent
89
+ if relation[:name]
90
+ data_row[relation[:name]] = row
91
+ else
92
+ data_row.merge!(row.reject{|key, value| key == relation[:foreign_key]})
93
+ end
94
+ end
95
+ end
96
+ end
97
+ options[:return_hash] ? data : results[0]
98
+ end
65
99
  end
66
100
 
101
+ def create_table(schema, table, columns_def)
102
+ execute <<-SQL
103
+ if not exists(select *
104
+ from sys.tables
105
+ inner join sys.schemas on tables.schema_id = schemas.schema_id
106
+ where
107
+ tables.name = '#{table}'
108
+ and schemas.name = '#{schema}')
109
+ create table #{schema}.#{table} (#{columns_def})
110
+ SQL
111
+ end
67
112
  private
68
113
 
69
114
  def connect
70
- print "connecting to #{@params[:host]} "
115
+ #print "connecting to #{@params[:host]} "
71
116
  @connection = TinyTds::Client.new(@params)
72
- print "successful\n"
117
+ #print "successful\n"
73
118
  rescue TinyTds::Error => e
74
- print "#{e.to_s}\n"
75
- throw unless @params[:mirror_host]
119
+ raise unless @params[:mirror_host]
120
+ #print "#{e.to_s}\n"
76
121
  to_mirror
77
122
  connect
78
123
  end
@@ -89,10 +134,10 @@ module Minus5
89
134
  # Returns array of table column names or stored procedure param
90
135
  def get_params(name)
91
136
  @params_cache[name] ||=
92
- begin
93
- sql = "select name from sys.syscolumns where id = object_id('#{name}')"
94
- @connection.execute(sql).each.map{|row| row["name"]}
95
- end
137
+ begin
138
+ sql = "select name from sys.syscolumns where id = object_id('#{name}')"
139
+ @connection.execute(sql).each.map{|row| row["name"]}
140
+ end
96
141
  end
97
142
 
98
143
  def hash_to_values(columns, data)
@@ -129,4 +174,4 @@ module Minus5
129
174
 
130
175
  end
131
176
 
132
- end
177
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'pp'
4
+
5
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
6
+ require 'minus5_mssql.rb'
7
+
8
+ module Helper
9
+
10
+ protected
11
+
12
+ def setup_table(adapter)
13
+ adapter.execute "
14
+ if not exists(select * from sys.objects where name = 'people')
15
+ create table people (id int identity, first_name varchar(255), last_name varchar(255))
16
+ "
17
+ adapter.execute "truncate table people"
18
+ adapter.execute "insert into people (first_name, last_name) values ('Sasa', 'Juric')"
19
+ adapter.execute "insert into people (first_name, last_name) values ('Goran', 'Pizent')"
20
+ end
21
+
22
+ def rollback_transaction(client)
23
+ client.execute("BEGIN TRANSACTION").do
24
+ yield
25
+ ensure
26
+ client.execute("ROLLBACK TRANSACTION").do
27
+ end
28
+
29
+ end
@@ -0,0 +1,120 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
+ require 'helper.rb'
3
+
4
+ class Select < Test::Unit::TestCase
5
+ include Helper
6
+
7
+ def setup
8
+ @reader = Minus5::Mssql::Adapter.new({:username => "rails",
9
+ :password => "",
10
+ :host => "mssql",
11
+ :database => "minus5_mssql_tests"})
12
+ create_tables
13
+ end
14
+
15
+ def test_select_value
16
+ assert_equal 1, @reader.select_value("select 1")
17
+ assert_equal 1, @reader.select_value("select 1, 2")
18
+ assert_equal 1, @reader.select_value("select 1\nunion\nselect 2")
19
+ assert_equal 1, @reader.select_value("select 1; select 2")
20
+ assert_nil @reader.select_value("set nocount on")
21
+ end
22
+
23
+ def test_select_values
24
+ assert_equal [1,2], @reader.select_values("select 1, 11\nunion\nselect 2, 22")
25
+ assert_equal [1,2], @reader.select_values("select 1, 11\nunion\nselect 2, 22; select 3, 3")
26
+ assert_equal [], @reader.select_values("set nocount on")
27
+ end
28
+
29
+ def test_select_simple
30
+ assert_equal([{:first => 1, :second => 2}], @reader.select("select 1 first, 2 second"))
31
+ assert_equal([{:first => 1, :second => 2}], @reader.select(:sql=>"select 1 first, 2 second"))
32
+ assert_equal [], @reader.select("set nocount on")
33
+ end
34
+
35
+ def test_get_params
36
+ columns = @reader.send(:get_params, 'people')
37
+ assert_equal 3, columns.size
38
+ assert columns.include?("id")
39
+ assert columns.include?("first_name")
40
+ assert columns.include?("last_name")
41
+ end
42
+
43
+ def test_insert_delete
44
+ id = @reader.insert('people', {:first_name => "Igor", :last_name => "Anic"})
45
+ assert_equal 3, @reader.select_value("select count(*) from people")
46
+ @reader.delete('people', {:id => id})
47
+ assert_equal 2, @reader.select_value("select count(*) from people")
48
+ end
49
+
50
+
51
+ def test_simple_select
52
+ result = @reader.select("select * from orders")
53
+ assert result.kind_of?(Array)
54
+ assert_equal 3, result.size
55
+ assert_equal 3, result[0].keys.size
56
+ end
57
+
58
+ def test_parent_child_one_to_many_and_one_to_one
59
+ result = @reader.select(
60
+ :sql=>"select * from orders; select * from order_details order by no; select order_id, sum(no) sum_no from order_details group by order_id",
61
+ :primary_key=>:id,
62
+ :relations=>[{:type=>:one_to_many, :name=>:order_details, :foreign_key=>:order_id},
63
+ {:type=>:one_to_one, :foreign_key=>:order_id}]
64
+ )
65
+ assert result.kind_of?(Array)
66
+ assert_equal 3, result.size
67
+ assert_equal 5, result[0].keys.size
68
+ 3.times do |i|
69
+ parent = result[i]
70
+ childs = parent[:order_details]
71
+ assert childs.kind_of?(Array)
72
+ assert_equal 5, childs.size
73
+ childs.each_with_index do |child, j|
74
+ assert_equal i+1, child[:order_id]
75
+ assert_equal j, child[:no]
76
+ end
77
+ assert_not_nil parent[:sum_no]
78
+ end
79
+ #pp result
80
+ end
81
+
82
+ def test_one_to_one
83
+ result = @reader.select(
84
+ :sql=>"select * from orders; select order_id, sum(no) sum_no from order_details group by order_id",
85
+ :primary_key=>:id,
86
+ :relations=>[{:type=>:one_to_one, :name=>:sum, :foreign_key=>:order_id}]
87
+ )
88
+ #pp result
89
+ assert_equal 4, result[0].keys.size
90
+ assert result[0][:sum].kind_of?(Hash)
91
+ end
92
+
93
+ private
94
+
95
+ def create_tables
96
+ @reader.create_table "dbo", "people",
97
+ "id int identity, first_name varchar(255), last_name varchar(255)"
98
+ @reader.execute "truncate table dbo.people"
99
+ @reader.insert "dbo.people", {:first_name=>"Sasa", :last_name=>"Juric"}
100
+ @reader.insert "dbo.people", {:first_name=>"Goran", :last_name=>"Pizent"}
101
+
102
+ @reader.create_table "dbo", "orders",
103
+ "id int identity, created datetime, amount money"
104
+ @reader.create_table "dbo", "order_details",
105
+ "id int identity, order_id int, no int"
106
+ @reader.execute "truncate table dbo.orders"
107
+ @reader.execute "truncate table dbo.order_details"
108
+ 3.times do |o|
109
+ id = @reader.insert "orders", {:created=>Time.now, :amount=>1234.5 * (o + 1)}
110
+ 5.times{|no| @reader.insert "order_details", {:order_id=>id, :no=>no}}
111
+ end
112
+ @reader.execute "drop procedure all_orders"
113
+ @reader.execute <<-SQL
114
+ create procedure all_orders as
115
+ select * from orders
116
+ select order_id parent_id, * from order_details
117
+ SQL
118
+ end
119
+
120
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minus5_mssql
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Igor Anic
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-31 00:00:00 +02:00
18
+ date: 2011-07-05 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -45,7 +45,9 @@ extra_rdoc_files: []
45
45
  files:
46
46
  - lib/minus5_mssql.rb
47
47
  - lib/minus5_mssql/adapter.rb
48
+ - test/helper.rb
48
49
  - test/test_db_mirroring.rb
50
+ - test/test_select.rb
49
51
  - Rakefile
50
52
  has_rdoc: true
51
53
  homepage: http://www.minus5.hr