data_objects 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 (45) hide show
  1. data/Manifest.txt +19 -1
  2. data/Rakefile +6 -80
  3. data/lib/data_objects.rb +1 -6
  4. data/lib/data_objects/command.rb +51 -1
  5. data/lib/data_objects/connection.rb +13 -2
  6. data/lib/data_objects/logger.rb +40 -32
  7. data/lib/data_objects/quoting.rb +28 -32
  8. data/lib/data_objects/reader.rb +6 -5
  9. data/lib/data_objects/result.rb +7 -1
  10. data/lib/data_objects/spec/command_spec.rb +191 -0
  11. data/lib/data_objects/spec/connection_spec.rb +106 -0
  12. data/lib/data_objects/spec/encoding_spec.rb +31 -0
  13. data/lib/data_objects/spec/quoting_spec.rb +0 -0
  14. data/lib/data_objects/spec/reader_spec.rb +156 -0
  15. data/lib/data_objects/spec/result_spec.rb +58 -0
  16. data/lib/data_objects/spec/typecast/array_spec.rb +36 -0
  17. data/lib/data_objects/spec/typecast/bigdecimal_spec.rb +107 -0
  18. data/lib/data_objects/spec/typecast/boolean_spec.rb +107 -0
  19. data/lib/data_objects/spec/typecast/byte_array_spec.rb +86 -0
  20. data/lib/data_objects/spec/typecast/class_spec.rb +63 -0
  21. data/lib/data_objects/spec/typecast/date_spec.rb +108 -0
  22. data/lib/data_objects/spec/typecast/datetime_spec.rb +110 -0
  23. data/lib/data_objects/spec/typecast/float_spec.rb +111 -0
  24. data/lib/data_objects/spec/typecast/integer_spec.rb +86 -0
  25. data/lib/data_objects/spec/typecast/ipaddr_spec.rb +0 -0
  26. data/lib/data_objects/spec/typecast/nil_spec.rb +116 -0
  27. data/lib/data_objects/spec/typecast/range_spec.rb +36 -0
  28. data/lib/data_objects/spec/typecast/string_spec.rb +86 -0
  29. data/lib/data_objects/spec/typecast/time_spec.rb +64 -0
  30. data/lib/data_objects/transaction.rb +20 -13
  31. data/lib/data_objects/uri.rb +24 -2
  32. data/lib/data_objects/version.rb +2 -1
  33. data/spec/command_spec.rb +1 -17
  34. data/spec/connection_spec.rb +1 -23
  35. data/spec/lib/pending_helpers.rb +11 -0
  36. data/spec/lib/rspec_immediate_feedback_formatter.rb +53 -0
  37. data/spec/result_spec.rb +0 -3
  38. data/tasks/gem.rake +49 -0
  39. data/tasks/install.rake +13 -0
  40. data/tasks/release.rake +74 -0
  41. data/tasks/spec.rake +18 -0
  42. metadata +51 -30
  43. data/.gitignore +0 -2
  44. data/spec/dataobjects_spec.rb +0 -1
  45. data/spec/spec.opts +0 -2
@@ -0,0 +1,36 @@
1
+ share_examples_for 'supporting Range' do
2
+
3
+ include DataObjectsSpecHelpers
4
+
5
+ before :all do
6
+ setup_test_environment
7
+ end
8
+
9
+ before :each do
10
+ @connection = DataObjects::Connection.new(CONFIG.uri)
11
+ end
12
+
13
+ after :each do
14
+ @connection.close
15
+ end
16
+
17
+ describe 'passing a Range as a parameter in execute_reader' do
18
+
19
+ before do
20
+ @reader = @connection.create_command("SELECT * FROM widgets WHERE id between ?").execute_reader(2..5)
21
+ end
22
+
23
+ after do
24
+ @reader.close
25
+ end
26
+
27
+ it 'should return correct number of rows' do
28
+ counter = 0
29
+ while(@reader.next!) do
30
+ counter += 1
31
+ end
32
+ counter.should == 4
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,86 @@
1
+ share_examples_for 'supporting String' do
2
+
3
+ include DataObjectsSpecHelpers
4
+
5
+ before :all do
6
+ setup_test_environment
7
+ end
8
+
9
+ before :each do
10
+ @connection = DataObjects::Connection.new(CONFIG.uri)
11
+ end
12
+
13
+ after :each do
14
+ @connection.close
15
+ end
16
+
17
+ describe 'reading a String' do
18
+
19
+ describe 'with automatic typecasting' do
20
+
21
+ before do
22
+ @reader = @connection.create_command("SELECT code FROM widgets WHERE ad_description = ?").execute_reader('Buy this product now!')
23
+ @reader.next!
24
+ @values = @reader.values
25
+ end
26
+
27
+ after do
28
+ @reader.close
29
+ end
30
+
31
+ it 'should return the correctly typed result' do
32
+ @values.first.should be_kind_of(String)
33
+ end
34
+
35
+ it 'should return the correct result' do
36
+ @values.first.should == "W0000001"
37
+ end
38
+
39
+ end
40
+
41
+ describe 'with manual typecasting' do
42
+
43
+ before do
44
+ @command = @connection.create_command("SELECT weight FROM widgets WHERE ad_description = ?")
45
+ @command.set_types(String)
46
+ @reader = @command.execute_reader('Buy this product now!')
47
+ @reader.next!
48
+ @values = @reader.values
49
+ end
50
+
51
+ after do
52
+ @reader.close
53
+ end
54
+
55
+ it 'should return the correctly typed result' do
56
+ @values.first.should be_kind_of(String)
57
+ end
58
+
59
+ it 'should return the correct result' do
60
+ @values.first.should == "13.4"
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ describe 'writing a String' do
68
+
69
+ before do
70
+ @reader = @connection.create_command("SELECT id FROM widgets WHERE id = ?").execute_reader("2")
71
+ @reader.next!
72
+ @values = @reader.values
73
+ end
74
+
75
+ after do
76
+ @reader.close
77
+ end
78
+
79
+ it 'should return the correct entry' do
80
+ # Some of the drivers starts autoincrementation from 0 not 1
81
+ @values.first.should satisfy { |val| val == 1 or val == 2 }
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,64 @@
1
+ share_examples_for 'supporting Time' do
2
+
3
+ include DataObjectsSpecHelpers
4
+
5
+ before :all do
6
+ setup_test_environment
7
+ end
8
+
9
+ before :each do
10
+ @connection = DataObjects::Connection.new(CONFIG.uri)
11
+ end
12
+
13
+ after :each do
14
+ @connection.close
15
+ end
16
+
17
+ describe 'reading a Time' do
18
+
19
+ describe 'with manual typecasting' do
20
+
21
+ before do
22
+ @command = @connection.create_command("SELECT release_date FROM widgets WHERE ad_description = ?")
23
+ @command.set_types(Time)
24
+ @reader = @command.execute_reader('Buy this product now!')
25
+ @reader.next!
26
+ @values = @reader.values
27
+ end
28
+
29
+ after do
30
+ @reader.close
31
+ end
32
+
33
+ it 'should return the correctly typed result' do
34
+ @values.first.should be_kind_of(Time)
35
+ end
36
+
37
+ it 'should return the correct result' do
38
+ @values.first.should == Time.local(2008, 2, 14)
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
45
+ describe 'writing an Time' do
46
+
47
+ before do
48
+ @reader = @connection.create_command("SELECT id FROM widgets WHERE release_datetime = ?").execute_reader(Time.utc(2008, 2, 14, 00, 31, 12))
49
+ @reader.next!
50
+ @values = @reader.values
51
+ end
52
+
53
+ after do
54
+ @reader.close
55
+ end
56
+
57
+ it 'should return the correct entry' do
58
+ #Some of the drivers starts autoincrementation from 0 not 1
59
+ @values.first.should satisfy { |val| val == 1 or val == 0 }
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -5,41 +5,48 @@ module DataObjects
5
5
 
6
6
  class Transaction
7
7
 
8
+ # The host name. Note, this relies on the host name being configured and resolvable using DNS
8
9
  HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
9
10
  @@counter = 0
10
11
 
12
+ # The connection object allocated for this transaction
11
13
  attr_reader :connection
14
+ # A unique ID for this transaction
12
15
  attr_reader :id
13
16
 
17
+ # Instantiate the Transaction subclass that's appropriate for this uri scheme
14
18
  def self.create_for_uri(uri)
15
19
  uri = uri.is_a?(String) ? URI::parse(uri) : uri
16
20
  DataObjects.const_get(uri.scheme.capitalize)::Transaction.new(uri)
17
21
  end
18
22
 
19
23
  #
20
- # Creates a Transaction bound to the given connection
21
- #
22
- # ==== Parameters
23
- # conn<DataObjects::Connection>:: The Connection to bind the new Transaction to
24
+ # Creates a Transaction bound to a connection for the given DataObjects::URI
24
25
  #
25
26
  def initialize(uri)
26
27
  @connection = DataObjects::Connection.new(uri)
27
28
  @id = Digest::SHA256.hexdigest("#{HOST}:#{$$}:#{Time.now.to_f}:#{@@counter += 1}")
28
29
  end
29
30
 
31
+ # Close the connection for this Transaction
30
32
  def close
31
33
  @connection.close
32
34
  end
33
35
 
34
- [:begin, :commit, :rollback, :rollback_prepared, :prepare].each do |method_name|
35
-
36
- eval <<EOF
37
- def #{method_name}
38
- raise NotImplementedError
39
- end
40
- EOF
41
-
36
+ # Begin the Transaction
37
+ def begin; not_implemented; end
38
+ # Commit changes made in this Transaction
39
+ def commit; not_implemented; end
40
+ # Rollback changes made in this Transaction
41
+ def rollback; not_implemented; end;
42
+ # Prepare this Transaction for the second phase of a two-phase commit
43
+ def prepare; not_implemented; end;
44
+ # Abandon the second phase of a two-phase commit and roll back the changes
45
+ def rollback_prepared; not_implemented; end;
46
+
47
+ private
48
+ def not_implemented
49
+ raise NotImplementedError
42
50
  end
43
-
44
51
  end
45
52
  end
@@ -2,15 +2,27 @@ gem 'addressable', '~>2.0'
2
2
  require 'addressable/uri'
3
3
 
4
4
  module DataObjects
5
- URI = Struct.new(:scheme, :user, :password, :host, :port, :path, :query, :fragment)
6
5
 
7
- class URI
6
+ # A DataObjects URI is of the form scheme://user:password@host:port/path#fragment
7
+ #
8
+ # The elements are all optional except scheme and path:
9
+ # scheme:: The name of a DBMS for which you have a do_\&lt;scheme\&gt; adapter gem installed. If scheme is *jdbc*, the actual DBMS is in the _path_ followed by a colon.
10
+ # user:: The name of the user to authenticate to the database
11
+ # password:: The password to use in authentication
12
+ # host:: The domain name (defaulting to localhost) where the database is available
13
+ # port:: The TCP/IP port number to use for the connection
14
+ # path:: The name or path to the database
15
+ # query:: Parameters for the connection, for example encoding=utf8
16
+ # fragment:: Not currently known to be in use, but available to the adapters
17
+ class URI < Struct.new(:scheme, :user, :password, :host, :port, :path, :query, :fragment)
18
+ # Make a DataObjects::URI object by parsing a string. Simply delegates to Addressable::URI::parse.
8
19
  def self.parse(uri)
9
20
  return uri if uri.kind_of?(self)
10
21
  uri = Addressable::URI::parse(uri) unless uri.kind_of?(Addressable::URI)
11
22
  self.new(uri.scheme, uri.user, uri.password, uri.host, uri.port, uri.path, uri.query_values, uri.fragment)
12
23
  end
13
24
 
25
+ # Display this URI object as a string
14
26
  def to_s
15
27
  string = ""
16
28
  string << "#{scheme}://" if scheme
@@ -30,5 +42,15 @@ module DataObjects
30
42
  string << "##{fragment}" if fragment
31
43
  string
32
44
  end
45
+
46
+ # Compare this URI to another for hashing
47
+ def eql?(other)
48
+ to_s.eql?(other.to_s)
49
+ end
50
+
51
+ # Hash this URI
52
+ def hash
53
+ to_s.hash
54
+ end
33
55
  end
34
56
  end
@@ -1,3 +1,4 @@
1
1
  module DataObjects
2
- VERSION = "0.9.11" unless defined?(DataObjects::VERSION)
2
+ # Current DataObjects Gem version
3
+ VERSION = "0.9.12" unless defined?(DataObjects::VERSION)
3
4
  end
data/spec/command_spec.rb CHANGED
@@ -10,15 +10,7 @@ describe DataObjects::Command do
10
10
  @connection.close
11
11
  end
12
12
 
13
- it "should assign the connection object to @connection" do
14
- @command.instance_variable_get("@connection").should == @connection
15
- end
16
-
17
- it "should assign the sql text to @text" do
18
- @command.instance_variable_get("@text").should == 'SQL STRING'
19
- end
20
-
21
- %w{connection execute_non_query execute_reader set_types to_s}.each do |meth|
13
+ %w{connection execute_non_query execute_reader set_types}.each do |meth|
22
14
  it "should respond to ##{meth}" do
23
15
  @command.should respond_to(meth.intern)
24
16
  end
@@ -30,12 +22,4 @@ describe DataObjects::Command do
30
22
  end
31
23
  end
32
24
 
33
- it "should make the connection object available in #connection" do
34
- @command.connection.should == @command.instance_variable_get("@connection")
35
- end
36
-
37
- it "should make the SQL text available in #to_s" do
38
- @command.to_s.should == @command.instance_variable_get("@text")
39
- end
40
-
41
25
  end
@@ -20,15 +20,6 @@ describe DataObjects::Connection do
20
20
  end
21
21
 
22
22
  describe "initialization" do
23
- it "should accept a regular connection uri as a String" do
24
- c = DataObjects::Connection.new('mock://localhost/database')
25
- # relying on the fact that mock connection sets @uri
26
- uri = c.instance_variable_get("@uri")
27
-
28
- uri.scheme.should == 'mock'
29
- uri.host.should == 'localhost'
30
- uri.path.should == '/database'
31
- end
32
23
 
33
24
  it "should accept a connection uri as a Addressable::URI" do
34
25
  c = DataObjects::Connection.new(Addressable::URI::parse('mock://localhost/database'))
@@ -41,21 +32,8 @@ describe DataObjects::Connection do
41
32
  c.should be_kind_of(DataObjects::Mock::Connection)
42
33
 
43
34
  c = DataObjects::Connection.new(Addressable::URI.parse('mock:jndi://jdbc/database'))
44
- #c.should be_kind_of(DataObjects::Mock::Connection)
35
+ c.should be_kind_of(DataObjects::Mock::Connection)
45
36
  end
46
37
 
47
- it "should return the Connection using username" do
48
- c = DataObjects::Connection.new(Addressable::URI.parse('mock://root@localhost/database'))
49
- c.instance_variable_get(:@uri).user.should == 'root'
50
- c.instance_variable_get(:@uri).password.should be_nil
51
-
52
- c = DataObjects::Connection.new(Addressable::URI.parse('mock://root:@localhost/database'))
53
- c.instance_variable_get(:@uri).user.should == 'root'
54
- c.instance_variable_get(:@uri).password.should == ''
55
-
56
- c = DataObjects::Connection.new(Addressable::URI.parse('mock://root:pwd@localhost/database'))
57
- c.instance_variable_get(:@uri).user.should == 'root'
58
- c.instance_variable_get(:@uri).password.should == 'pwd'
59
- end
60
38
  end
61
39
  end
@@ -0,0 +1,11 @@
1
+ module DataObjects::Spec
2
+ module PendingHelpers
3
+ def pending_if(message, boolean)
4
+ if boolean
5
+ pending(message) { yield }
6
+ else
7
+ yield
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec/runner/formatter/base_text_formatter'
2
+
3
+ # Code is based on standard SpecdocFormatter, but will print full error details as soon as they are found.
4
+ # Successful or pending examples are written only as a dot in the output. Header is only printed if errors occur.
5
+ #
6
+ # To use it, add the following to your spec/spec.opts:
7
+ # --require
8
+ # lib/rspec_immediate_feedback_formatter.rb
9
+ # --format
10
+ # Spec::Runner::Formatter::ImmediateFeedbackFormatter
11
+
12
+ module Spec
13
+ module Runner
14
+ module Formatter
15
+ class ImmediateFeedbackFormatter < BaseTextFormatter
16
+
17
+ def add_example_group(example_group)
18
+ super
19
+ @current_group = example_group.description
20
+ end
21
+
22
+ def example_failed(example, counter, failure)
23
+ if @current_group
24
+ output.puts
25
+ output.puts @current_group
26
+ @current_group = nil # only print the group name once
27
+ end
28
+
29
+ message = if failure.expectation_not_met?
30
+ "- #{example.description} (FAILED - #{counter})"
31
+ else
32
+ "- #{example.description} (ERROR - #{counter})"
33
+ end
34
+
35
+ output.puts(red(message))
36
+ dump_failure(counter, failure) # dump stacktrace immediately
37
+ output.flush
38
+ end
39
+
40
+ def example_passed(*)
41
+ output.print green('.')
42
+ output.flush
43
+ end
44
+
45
+ def example_pending(*)
46
+ super
47
+ output.print yellow('*')
48
+ output.flush
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
data/spec/result_spec.rb CHANGED
@@ -9,9 +9,6 @@ describe DataObjects::Result do
9
9
 
10
10
  result = command.execute_non_query
11
11
 
12
- # In case the driver needs to access the command or connection to load additional data.
13
- result.instance_variables.map { |i| i.to_s }.should include('@command')
14
-
15
12
  # Affected Rows:
16
13
  result.should respond_to(:to_i)
17
14
  result.to_i.should == 0