File: command_spec.rb

package info (click to toggle)
ruby-dataobjects 0.10.8-4
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 416 kB
  • sloc: ruby: 2,917; makefile: 4
file content (234 lines) | stat: -rw-r--r-- 6,897 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
WINDOWS = false

shared_examples_for 'a Command' do

  before :all do
    setup_test_environment
  end

  before do
    @connection = DataObjects::Connection.new(CONFIG.uri)
    @command    = @connection.create_command("INSERT INTO users (name) VALUES (?)")
    @reader     = @connection.create_command("SELECT code, name FROM widgets WHERE ad_description = ?")
  end

  after do
    @connection.close
  end

  it { @command.should be_kind_of(DataObjects::Command) }

  it { @command.should respond_to(:execute_non_query) }

  describe 'execute_non_query' do

    describe 'with an invalid statement' do

      before do
        @invalid_command = @connection.create_command("INSERT INTO non_existent_table (tester) VALUES (1)")
      end

      it 'should raise an error on an invalid query' do
        expect { @invalid_command.execute_non_query }.to raise_error(DataObjects::SQLError)
      end

      it 'should raise an error with too few binding parameters' do
        expect { @command.execute_non_query("Too", "Many") }.to raise_error(ArgumentError,
          /Binding mismatch: 2 for 1/)
      end

      it 'should raise an error with too many binding parameters' do
        expect { @command.execute_non_query }.to raise_error(ArgumentError,
          /Binding mismatch: 0 for 1/)
      end

    end

    describe 'with a valid statement' do

      it 'should not raise an error with an explicit nil as parameter' do
        expect { @command.execute_non_query(nil) }.not_to raise_error(ArgumentError)
      end

    end

    describe 'with a valid statement and ? inside quotes' do

      before do
        @command_with_quotes = @connection.create_command("INSERT INTO users (name) VALUES ('will it work? ')")
      end

      it 'should not raise an error' do
        expect { @command_with_quotes.execute_non_query }.not_to raise_error(ArgumentError)
      end

    end

  end

  it { @command.should respond_to(:execute_reader) }

  describe 'execute_reader' do

    describe 'with an invalid reader' do

      before do
        @invalid_reader = @connection.create_command("SELECT * FROM non_existent_widgets WHERE ad_description = ?")
      end

      it 'should raise an error on an invalid query' do
        # FIXME JRuby (and MRI): Should this be an ArgumentError or DataObjects::SQLError?
        expect { @invalid_reader.execute_reader }.to raise_error # (ArgumentError, DataObjects::SQLError)
      end

      it 'should raise an error with too few binding parameters' do
        expect { @reader.execute_reader("Too", "Many") }.to raise_error(ArgumentError,
          /Binding mismatch: 2 for 1/)
      end

      it 'should raise an error with too many binding parameters' do
        expect { @reader.execute_reader }.to raise_error(ArgumentError,
          /Binding mismatch: 0 for 1/)
      end

    end

    describe 'with a valid reader' do

      it 'should not raise an error with an explicit nil as parameter' do
        expect { @reader.execute_reader(nil) }.not_to raise_error(ArgumentError)
      end

    end

    describe 'with a valid reader and ? inside column alias' do

      before do
        @reader_with_quotes = @connection.create_command("SELECT code AS \"code?\", name FROM widgets WHERE ad_description = ?")
      end

      it 'should not raise an error' do
        expect { @reader_with_quotes.execute_reader(nil) }.not_to raise_error(ArgumentError)
      end

    end


  end

  it { @command.should respond_to(:set_types) }

  describe 'set_types' do

    describe 'is invalid when used with a statement' do

      before do
        @command.set_types(String)
      end

      it 'should raise an error when types are set' do
        expect { @command.execute_non_query }.to raise_error(ArgumentError)
      end

    end

    describe 'with an invalid reader' do

      it 'should raise an error with too few types' do
        @reader.set_types(String)
        expect { @reader.execute_reader("One parameter") }.to raise_error(ArgumentError,
          /Field-count mismatch. Expected 1 fields, but the query yielded 2/)
      end

      it 'should raise an error with too many types' do
        @reader.set_types(String, String, BigDecimal)
        expect { @reader.execute_reader("One parameter") }.to raise_error(ArgumentError,
          /Field-count mismatch. Expected 3 fields, but the query yielded 2/)
      end

    end

    describe 'with a valid reader' do

      it 'should not raise an error with correct number of types' do
        @reader.set_types(String, String)
        expect { @result = @reader.execute_reader('Buy this product now!') }.not_to raise_error(ArgumentError)
        expect { @result.next!  }.not_to raise_error(DataObjects::DataError)
        expect { @result.values }.not_to raise_error(DataObjects::DataError)
        @result.close
      end

      it 'should also support old style array argument types' do
        @reader.set_types([String, String])
        expect { @result = @reader.execute_reader('Buy this product now!') }.not_to raise_error(ArgumentError)
        expect { @result.next!  }.not_to raise_error(DataObjects::DataError)
        expect { @result.values }.not_to raise_error(DataObjects::DataError)
        @result.close
      end

      it 'should allow subtype types' do
        class MyString < String; end
        @reader.set_types(MyString, String)
        expect { @result = @reader.execute_reader('Buy this product now!') }.not_to raise_error(ArgumentError)
        expect { @result.next!  }.not_to raise_error(DataObjects::DataError)
        expect { @result.values }.not_to raise_error(DataObjects::DataError)
        @result.close
      end
    end

  end

  it { @command.should respond_to(:to_s) }

  describe 'to_s' do

  end


end

shared_examples_for 'a Command with async' do

  before :all do
    setup_test_environment
  end

  describe 'running queries in parallel' do

    before do

      threads = []

      @start = Time.now
      4.times do |i|
        threads << Thread.new do
          begin
            connection = DataObjects::Connection.new(CONFIG.uri)
            command = connection.create_command(CONFIG.sleep)
            if CONFIG.sleep =~ /^SELECT/i
              reader = command.execute_reader
              reader.next!
              reader.close
            else
              result = command.execute_non_query
            end
          ensure
            # Always make sure the connection gets released back into the pool.
            connection.close
          end
        end
      end

      threads.each{|t| t.join }
      @finish = Time.now
    end

    #Temporarily deactivate this example, as it currently fails with hurd-i386 and freebsd-i386
    xit "should finish within 2 seconds" do
      pending_if("Ruby on Windows doesn't support asynchronous operations", WINDOWS) do
        (@finish - @start).should < 2
      end
    end

  end
end