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.
- data/Manifest.txt +19 -1
- data/Rakefile +6 -80
- data/lib/data_objects.rb +1 -6
- data/lib/data_objects/command.rb +51 -1
- data/lib/data_objects/connection.rb +13 -2
- data/lib/data_objects/logger.rb +40 -32
- data/lib/data_objects/quoting.rb +28 -32
- data/lib/data_objects/reader.rb +6 -5
- data/lib/data_objects/result.rb +7 -1
- data/lib/data_objects/spec/command_spec.rb +191 -0
- data/lib/data_objects/spec/connection_spec.rb +106 -0
- data/lib/data_objects/spec/encoding_spec.rb +31 -0
- data/lib/data_objects/spec/quoting_spec.rb +0 -0
- data/lib/data_objects/spec/reader_spec.rb +156 -0
- data/lib/data_objects/spec/result_spec.rb +58 -0
- data/lib/data_objects/spec/typecast/array_spec.rb +36 -0
- data/lib/data_objects/spec/typecast/bigdecimal_spec.rb +107 -0
- data/lib/data_objects/spec/typecast/boolean_spec.rb +107 -0
- data/lib/data_objects/spec/typecast/byte_array_spec.rb +86 -0
- data/lib/data_objects/spec/typecast/class_spec.rb +63 -0
- data/lib/data_objects/spec/typecast/date_spec.rb +108 -0
- data/lib/data_objects/spec/typecast/datetime_spec.rb +110 -0
- data/lib/data_objects/spec/typecast/float_spec.rb +111 -0
- data/lib/data_objects/spec/typecast/integer_spec.rb +86 -0
- data/lib/data_objects/spec/typecast/ipaddr_spec.rb +0 -0
- data/lib/data_objects/spec/typecast/nil_spec.rb +116 -0
- data/lib/data_objects/spec/typecast/range_spec.rb +36 -0
- data/lib/data_objects/spec/typecast/string_spec.rb +86 -0
- data/lib/data_objects/spec/typecast/time_spec.rb +64 -0
- data/lib/data_objects/transaction.rb +20 -13
- data/lib/data_objects/uri.rb +24 -2
- data/lib/data_objects/version.rb +2 -1
- data/spec/command_spec.rb +1 -17
- data/spec/connection_spec.rb +1 -23
- data/spec/lib/pending_helpers.rb +11 -0
- data/spec/lib/rspec_immediate_feedback_formatter.rb +53 -0
- data/spec/result_spec.rb +0 -3
- data/tasks/gem.rake +49 -0
- data/tasks/install.rake +13 -0
- data/tasks/release.rake +74 -0
- data/tasks/spec.rake +18 -0
- metadata +51 -30
- data/.gitignore +0 -2
- data/spec/dataobjects_spec.rb +0 -1
- 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
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
def
|
38
|
-
|
39
|
-
end
|
40
|
-
|
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
|
data/lib/data_objects/uri.rb
CHANGED
@@ -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
|
-
|
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_\<scheme\> 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
|
data/lib/data_objects/version.rb
CHANGED
data/spec/command_spec.rb
CHANGED
@@ -10,15 +10,7 @@ describe DataObjects::Command do
|
|
10
10
|
@connection.close
|
11
11
|
end
|
12
12
|
|
13
|
-
|
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
|
data/spec/connection_spec.rb
CHANGED
@@ -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
|
-
|
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,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
|