data_objects 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 (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