do_postgres 0.9.11 → 0.9.12

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.
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