do_postgres 0.9.11 → 0.9.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/LICENSE +1 -1
  2. data/Manifest.txt +15 -5
  3. data/Rakefile +7 -121
  4. data/ext/do_postgres_ext/do_postgres_ext.c +245 -108
  5. data/ext/do_postgres_ext/extconf.rb +3 -1
  6. data/lib/do_postgres.rb +5 -2
  7. data/lib/do_postgres/version.rb +1 -1
  8. data/spec/command_spec.rb +9 -0
  9. data/spec/connection_spec.rb +19 -0
  10. data/spec/encoding_spec.rb +8 -0
  11. data/spec/lib/rspec_immediate_feedback_formatter.rb +3 -0
  12. data/spec/reader_spec.rb +8 -0
  13. data/spec/result_spec.rb +86 -0
  14. data/spec/spec_helper.rb +90 -57
  15. data/spec/typecast/array_spec.rb +8 -0
  16. data/spec/typecast/bigdecimal_spec.rb +9 -0
  17. data/spec/typecast/boolean_spec.rb +9 -0
  18. data/spec/typecast/byte_array_spec.rb +8 -0
  19. data/spec/typecast/class_spec.rb +8 -0
  20. data/spec/typecast/date_spec.rb +9 -0
  21. data/spec/typecast/datetime_spec.rb +9 -0
  22. data/spec/typecast/float_spec.rb +9 -0
  23. data/spec/typecast/integer_spec.rb +8 -0
  24. data/spec/typecast/nil_spec.rb +10 -0
  25. data/spec/typecast/range_spec.rb +8 -0
  26. data/spec/typecast/string_spec.rb +8 -0
  27. data/spec/typecast/time_spec.rb +8 -0
  28. data/tasks/gem.rake +61 -0
  29. data/tasks/install.rake +15 -0
  30. data/tasks/native.rake +35 -0
  31. data/tasks/release.rake +75 -0
  32. data/tasks/retrieve.rake +79 -0
  33. data/tasks/spec.rake +18 -0
  34. metadata +72 -44
  35. data/.gitignore +0 -0
  36. data/autobuild.rb +0 -90
  37. data/buildfile +0 -27
  38. data/ext-java/src/main/java/DoPostgresExtService.java +0 -23
  39. data/ext-java/src/main/java/do_postgres/PostgresDriverDefinition.java +0 -12
  40. data/script/timezone_spec_runner.rb +0 -28
  41. data/script/timezones.txt +0 -562
  42. data/spec/integration/do_postgres_spec.rb +0 -312
  43. data/spec/integration/logging_spec.rb +0 -53
  44. data/spec/integration/quoting_spec.rb +0 -25
  45. data/spec/integration/timezone_spec.rb +0 -66
  46. data/spec/spec.opts +0 -2
  47. data/spec/unit/transaction_spec.rb +0 -28
@@ -1,312 +0,0 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
-
4
- #
5
- #
6
- # Create a postgres db named do_test that accepts connections
7
- # from localhost from the postgres user (without password) to enable this spec.
8
- #
9
- # You also need to allow passwordless access from localhost-
10
- # locate the following line in your pg_hba.conf file:
11
- #
12
- # # IPv4 local connections:
13
- # host all all 127.0.0.1/32 md5
14
- #
15
- # and replace 'md5' with 'trust' for these specs to work
16
- #
17
- #
18
-
19
- describe "DataObjects::Postgres::Connection" do
20
- include PostgresSpecHelpers
21
-
22
- it "should connect to the db" do
23
- connection = DataObjects::Connection.new(DO_POSTGRES_SPEC_URI)
24
- connection.close
25
- end
26
-
27
- it "should be able to send queries asynchronously in parallel" do
28
- pending "Asynchronous queries behaving oddly in JRuby" if JRUBY
29
- threads = []
30
-
31
- start = Time.now
32
- 4.times do |i|
33
- threads << Thread.new do
34
- connection = DataObjects::Connection.new(DO_POSTGRES_SPEC_URI)
35
- command = connection.create_command("SELECT pg_sleep(1)")
36
- result = command.execute_non_query
37
- end
38
- end
39
-
40
- threads.each{|t| t.join }
41
- finish = Time.now
42
- (finish - start).should < 2
43
- end
44
-
45
- end
46
-
47
- describe "DataObjects::Postgres::Command" do
48
- include PostgresSpecHelpers
49
-
50
- before :all do
51
- @connection = ensure_users_table_and_return_connection
52
- end
53
-
54
- after :all do
55
- @connection.close
56
- end
57
-
58
- it "should create a command" do
59
- @connection.create_command("CREATE TABLE users").should be_a_kind_of(DataObjects::Postgres::Command)
60
- end
61
-
62
- it "should set types" do
63
- command = @connection.create_command("SELECT id, name FROM users")
64
- command.set_types [Integer, String]
65
- # NOTE: should we really be testing for the presence of instance variables?
66
- command.instance_variable_get(JRUBY ? "@types" : "@field_types").should == [Integer, String]
67
- end
68
-
69
- it "should execute a non query" do
70
- command = @connection.create_command("INSERT INTO users (name) VALUES ('Test')")
71
- result = command.execute_non_query
72
- result.should be_a_kind_of(DataObjects::Postgres::Result)
73
- end
74
-
75
- it "should execute a reader" do
76
- command = @connection.create_command("SELECT * FROM users")
77
- reader = command.execute_reader
78
- reader.should be_a_kind_of(DataObjects::Postgres::Reader)
79
- reader.close.should == true
80
- end
81
- end
82
-
83
- describe "DataObjects::Postgres::Result" do
84
- include PostgresSpecHelpers
85
-
86
- before :all do
87
- @connection = ensure_users_table_and_return_connection
88
- end
89
-
90
- after :all do
91
- @connection.close
92
- end
93
-
94
- it "should raise errors on bad queries" do
95
- command = @connection.create_command("INSER INTO users (name) VALUES ('Test')")
96
- lambda { command.execute_non_query }.should raise_error
97
- command = @connection.create_command("INSERT INTO users (non_existant_field) VALUES ('Test')")
98
- lambda { command.execute_non_query }.should raise_error
99
- end
100
-
101
- it "should not have an insert_id without RETURNING" do
102
- command = @connection.create_command("INSERT INTO users (name) VALUES ('Test')")
103
- result = command.execute_non_query
104
- result.insert_id.should == 0;
105
- result.to_i.should == 1;
106
- end
107
-
108
- it "should have an insert_id when RETURNING" do
109
- command = @connection.create_command("INSERT INTO users (name) VALUES ('Test') RETURNING id")
110
- result = command.execute_non_query
111
- result.insert_id.should_not == 0;
112
- result.to_i.should == 1;
113
- end
114
- end
115
-
116
- describe "DataObjects::Postgres::Reader" do
117
- include PostgresSpecHelpers
118
-
119
- before :all do
120
- @connection = ensure_users_table_and_return_connection
121
- @connection.create_command("INSERT INTO users (name) VALUES ('Test')").execute_non_query
122
- @connection.create_command("INSERT INTO users (name) VALUES ('Test')").execute_non_query
123
- @connection.create_command("INSERT INTO users (name) VALUES ('Test')").execute_non_query
124
- end
125
-
126
- it "should raise errors on bad queries" do
127
- command = @connection.create_command("SELT * FROM users")
128
- lambda { command.execute_reader }.should raise_error
129
- command = @connection.create_command("SELECT * FROM non_existant_table")
130
- lambda { command.execute_reader }.should raise_error
131
- end
132
-
133
- it "should open and close a reader with given types of columns" do
134
- command = @connection.create_command("SELECT id, name FROM users LIMIT 3")
135
- command.set_types [Integer, String ]
136
- reader = command.execute_reader
137
- reader.close.should == true
138
- end
139
-
140
- it "should open and close a reader without given types of columns" do
141
- command = @connection.create_command("SELECT * FROM users LIMIT 3")
142
- reader = command.execute_reader
143
- reader.close.should == true
144
- end
145
-
146
- it "should raise error on wrong number of columns calling set_types" do
147
- pending "C-extension does not raise an error on encountering wrong number of columns" unless JRUBY
148
- command = @connection.create_command("SELECT * FROM users LIMIT 3")
149
- command.set_types [Integer, String]
150
- lambda { reader = command.execute_reader }.should raise_error
151
- end
152
-
153
- it "should return proper number of rows and fields using row_count and field_count" do
154
- pending "do_jdbc doesn't return correctly row_count at the moment" if JRUBY
155
- command = @connection.create_command("SELECT id, name, registered, money FROM users ORDER BY id DESC LIMIT 3")
156
- reader = command.execute_reader
157
- reader.field_count.should == 4
158
- reader.row_count.should == 3
159
- reader.close
160
- end
161
-
162
- it "should typecast a value from the postgres type" do
163
- command = @connection.create_command("SELECT id, name, registered, money FROM users ORDER BY id DESC LIMIT 3")
164
- reader = command.execute_reader
165
- while ( reader.next!)
166
- reader.values[0].should be_a_kind_of(Integer)
167
- reader.values[1].should be_a_kind_of(String)
168
- reader.values[2].should == false
169
- reader.values[3].should == 1908.56
170
- end
171
- reader.close
172
- end
173
-
174
- it "should typecast from set_types" do
175
- command = @connection.create_command("SELECT id, name FROM users ORDER BY id LIMIT 1")
176
- command.set_types [Integer, String]
177
- reader = command.execute_reader
178
- reader.next!
179
- reader.values[0].should be_a_kind_of(Integer)
180
- reader.values[1].should be_a_kind_of(String)
181
- reader.close
182
- end
183
-
184
- it "should handle a null value" do
185
- id = insert("INSERT INTO users (name) VALUES (NULL)")
186
- select("SELECT name from users WHERE name is null") do |reader|
187
- reader.values[0].should == nil
188
- end
189
- end
190
-
191
- it "should return nil when the time is 0" do
192
- pending "We need to introduce something like Proxy for typeasting where each SQL type will have _rules_ of casting" if JRUBY
193
- pending "Fix zero representation of Time in PostgreSQL" unless JRUBY
194
- id = insert("INSERT INTO users (name, fired_at) VALUES ('James', '0000-00-00')")
195
- select("SELECT fired_at FROM users WHERE id = ?", [Time], id) do |reader|
196
- reader.values.last.should be_nil
197
- end
198
- exec("DELETE FROM users WHERE id = ?", id)
199
- end
200
-
201
- it "should not convert empty strings to null" do
202
- id = insert("INSERT INTO users (name) VALUES ('')")
203
- select("SELECT name FROM users WHERE id = ?", [String], id) do |reader|
204
- reader.values.first.should == ''
205
- end
206
- end
207
-
208
- it "should typecast a date field" do
209
- command = @connection.create_command("SELECT created_on FROM users WHERE created_on is not null LIMIT 1")
210
- reader = command.execute_reader
211
- reader.next!
212
- # do_jdbc currently returning Time
213
- reader.values[0].should be_a_kind_of(Date)
214
- end
215
-
216
- it "should typecast a BigDecimal field" do
217
- money_in_the_bank = BigDecimal.new('1.29')
218
-
219
- id = insert("INSERT INTO users (name, money) VALUES (?, ?)", "MC Hammer", money_in_the_bank)
220
- select("SELECT money FROM users WHERE id = ?", [BigDecimal], id) do |reader|
221
- reader.values.first.should == money_in_the_bank
222
- end
223
- end
224
-
225
- it "should return DateTimes using the current locale's Time Zone" do
226
- date = DateTime.now
227
- id = insert("INSERT INTO users (name, created_at) VALUES (?, ?)", 'Sam', date)
228
- select("SELECT created_at FROM users WHERE id = ?", [DateTime], id) do |reader|
229
- reader.values.last.to_s.should == date.to_s
230
- end
231
- exec("DELETE FROM users WHERE id = ?", id)
232
- end
233
-
234
- it "should typecast a timestamp field" do
235
- command = @connection.create_command("SELECT created_at FROM users WHERE created_at is not null LIMIT 1")
236
- reader = command.execute_reader
237
- reader.next!
238
- reader.values[0].should be_a_kind_of(DateTime)
239
-
240
- command = @connection.create_command("SELECT created_at::date as date FROM users WHERE created_at is not null LIMIT 1")
241
- reader = command.execute_reader
242
- reader.next!
243
- reader.values[0].should be_a_kind_of(Date)
244
-
245
- end
246
-
247
- it "should work on a join" do
248
-
249
- user = @connection.create_command("SELECT * FROM users WHERE id = 1").execute_reader
250
- user.next!
251
-
252
- @connection.create_command("INSERT INTO companies (name) VALUES ('ELEC')").execute_non_query
253
- reader = @connection.create_command(<<-EOF).execute_reader
254
- SELECT u.* FROM users AS u
255
- LEFT JOIN companies AS c
256
- ON u.company_id=c.id
257
- WHERE c.name='ELEC'
258
- EOF
259
- reader.next!
260
- reader.values.should == user.values
261
- end
262
-
263
- it "should not typecast a time field" do
264
- command = @connection.create_command("SELECT born_at FROM users LIMIT 1")
265
- reader = command.execute_reader
266
- reader.next!
267
- reader.values[0].should be_a_kind_of(String)
268
- end
269
-
270
- it "should typecast a timestamp field without time zone" do
271
- command = @connection.create_command("SELECT created_at FROM users LIMIT 1")
272
- reader = command.execute_reader
273
- reader.next!
274
- reader.values[0].should be_a_kind_of(DateTime)
275
- end
276
-
277
- it "should typecast a timestamp field with time zone" do
278
- command = @connection.create_command("SELECT fired_at FROM users LIMIT 1")
279
- reader = command.execute_reader
280
- reader.next!
281
- reader.values[0].should be_a_kind_of(DateTime)
282
- end
283
-
284
- it "should typecast a numeric field to a big decimal" do
285
- command = @connection.create_command("SELECT amount FROM users LIMIT 1")
286
- reader = command.execute_reader
287
- reader.next!
288
- reader.values[0].should be_a_kind_of(BigDecimal)
289
- end
290
-
291
- it "should return the current character set" do
292
- connection = DataObjects::Connection.new("postgres://#{POSTGRES.user}:#{POSTGRES.pass}@#{POSTGRES.hostname}:#{POSTGRES.port}/#{POSTGRES.database}")
293
- connection.character_set.should == "utf8"
294
- connection.close
295
- end
296
-
297
- it "should support changing the character set" do
298
- pending "JDBC API does not provide an easy way to get the current character set" if JRUBY
299
- # current character set can be retrieved with the following query:
300
- # "SHOW VARIABLES LIKE character_set_database"
301
-
302
- connection = DataObjects::Connection.new("postgres://#{POSTGRES.user}:#{POSTGRES.pass}@#{POSTGRES.hostname}:#{POSTGRES.port}/#{POSTGRES.database}?charset=latin1")
303
- # N.B. query parameter after forward slash causes problems with JDBC
304
- connection.character_set.should == "latin1"
305
- connection.close
306
-
307
- connection = DataObjects::Connection.new("postgres://#{POSTGRES.user}:#{POSTGRES.pass}@#{POSTGRES.hostname}:#{POSTGRES.port}/#{POSTGRES.database}?charset=utf8")
308
- connection.character_set.should == "utf8"
309
- connection.close
310
- end
311
-
312
- end
@@ -1,53 +0,0 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
-
4
- describe DataObjects::Postgres::Command do
5
-
6
- before(:each) do
7
- @connection = DataObjects::Connection.new(DO_POSTGRES_SPEC_URI)
8
- end
9
-
10
- after(:each) do
11
- @connection.close
12
- end
13
-
14
- describe "Executing a Reader" do
15
-
16
- it "should log reader queries when the level is Debug (0)" do
17
- command = @connection.create_command("SELECT * FROM users")
18
- @mock_logger = mock('MockLogger', :level => 0)
19
- DataObjects::Postgres.should_receive(:logger).and_return(@mock_logger)
20
- @mock_logger.should_receive(:debug).with(/\([\d.]+\) SELECT \* FROM users/)
21
- command.execute_reader.close
22
- end
23
-
24
- it "shouldn't log reader queries when the level isn't Debug (0)" do
25
- command = @connection.create_command("SELECT * FROM users")
26
- @mock_logger = mock('MockLogger', :level => 1)
27
- DataObjects::Postgres.should_receive(:logger).and_return(@mock_logger)
28
- @mock_logger.should_not_receive(:debug)
29
- command.execute_reader.close
30
- end
31
- end
32
-
33
- describe "Executing a Non-Query" do
34
- it "should log non-query statements when the level is Debug (0)" do
35
- command = @connection.create_command("INSERT INTO users (name) VALUES (?)")
36
- @mock_logger = mock('MockLogger', :level => 0)
37
- DataObjects::Postgres.should_receive(:logger).and_return(@mock_logger)
38
- # NOTE: debug string on JRuby does not insert quotation marks
39
- # on MRI, value is quoted
40
- @mock_logger.should_receive(:debug).with(/\([\d.]+\) INSERT INTO users \(name\) VALUES \((\'?)Blah(\'?)\)/)
41
- command.execute_non_query('Blah')
42
- end
43
-
44
- it "shouldn't log non-query statements when the level isn't Debug (0)" do
45
- command = @connection.create_command("INSERT INTO users (name) VALUES (?)")
46
- @mock_logger = mock('MockLogger', :level => 1)
47
- DataObjects::Postgres.should_receive(:logger).and_return(@mock_logger)
48
- @mock_logger.should_not_receive(:debug)
49
- command.execute_non_query('Blah')
50
- end
51
- end
52
-
53
- end
@@ -1,25 +0,0 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
-
4
- unless JRUBY
5
- describe DataObjects::Postgres::Command do
6
-
7
- before(:each) do
8
- @connection = DataObjects::Connection.new(DO_POSTGRES_SPEC_URI)
9
- @command = @connection.create_command("INSERT INTO users (name) VALUES (?)")
10
- end
11
-
12
- after(:each) do
13
- @connection.close
14
- end
15
-
16
- it "should properly quote a string" do
17
- @command.quote_string("O'Hare").should == "'O''Hare'"
18
- @command.quote_string("Willy O'Hare & Johnny O'Toole").should == "'Willy O''Hare & Johnny O''Toole'"
19
- @command.quote_string("Billy\\Bob").should == "'Billy\\Bob'"
20
- @command.quote_string("The\\Backslasher\\Rises\\Again").should == "'The\\Backslasher\\Rises\\Again'"
21
- @command.quote_string("Scott \"The Rage\" Bauer").should == "'Scott \"The Rage\" Bauer'"
22
- end
23
-
24
- end
25
- end
@@ -1,66 +0,0 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
-
4
- describe "DataObjects::Postgres::Reader" do
5
- include PostgresSpecHelpers
6
-
7
- before :all do
8
- @connection = ensure_users_table_and_return_connection
9
- Time.now.to_s.match(/([-+]\d{2})(\d{2})/)
10
- @connection.create_command("SET SESSION TIME ZONE INTERVAL '#{$1}:#{$2}' HOUR TO MINUTE").execute_non_query
11
- @connection.create_command("INSERT INTO users (name) VALUES ('Test')").execute_non_query
12
- @connection.create_command("INSERT INTO users (name) VALUES ('Test')").execute_non_query
13
- @connection.create_command("INSERT INTO users (name) VALUES ('Test')").execute_non_query
14
- end
15
-
16
- after :all do
17
- @connection.close
18
- end
19
-
20
- it "should return DateTimes using the current locale's Time Zone for TIMESTAMP WITHOUT TIME ZONE fields" do
21
- date = DateTime.now
22
- id = insert("INSERT INTO users (name, created_at) VALUES (?, ?)", 'Sam', date)
23
-
24
- select("SELECT created_at FROM users WHERE id = ?", [DateTime], id) do |reader|
25
- reader.values.last.to_s.should == date.to_s
26
- end
27
-
28
- exec("DELETE FROM users WHERE id = ?", id)
29
- end
30
-
31
- it "should return DateTimes using the current locale's Time Zone TIMESTAMP WITH TIME ZONE fields" do
32
- date = DateTime.now
33
- id = insert("INSERT INTO users (name, fired_at) VALUES (?, ?)", 'Sam', date)
34
-
35
- select("SELECT fired_at FROM users WHERE id = ?", [DateTime], id) do |reader|
36
- reader.values.last.to_s.should == date.to_s
37
- end
38
-
39
- exec("DELETE FROM users WHERE id = ?", id)
40
- end
41
-
42
- it "should return DateTimes using the current locale's Time Zone if they were inserted using a different timezone" do
43
- pending "We don't support non-local date input yet"
44
- now = DateTime.now
45
- dates = [
46
- now,
47
- now.new_offset( (-11 * 3600).to_r / 86400), # GMT -11:00
48
- now.new_offset( (-9 * 3600 + 10 * 60).to_r / 86400), # GMT -9:10
49
- now.new_offset( (-8 * 3600).to_r / 86400), # GMT -08:00
50
- now.new_offset( (+3 * 3600).to_r / 86400), # GMT +03:00
51
- now.new_offset( (+5 * 3600 + 30 * 60).to_r / 86400) # GMT +05:30 (New Delhi)
52
- ]
53
-
54
- dates.each do |date|
55
- id = insert("INSERT INTO users (name, fired_at) VALUES (?, ?)", 'Sam', date)
56
-
57
- select("SELECT name, fired_at FROM users WHERE id = ?", [String, DateTime], id) do |reader|
58
- reader.fields.should == ["name", "fired_at"]
59
- reader.values.last.to_s.should == now.to_s
60
- end
61
-
62
- exec("DELETE FROM users WHERE id = ?", id)
63
- end
64
- end
65
-
66
- end