nuodb 1.0.0.rc.1 → 1.0.0.rc.2

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.
@@ -0,0 +1,131 @@
1
+ require 'set'
2
+
3
+ module NuoDB
4
+
5
+ class Column
6
+ TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set
7
+ FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set
8
+
9
+ module Format
10
+ ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
11
+ ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
12
+ end
13
+
14
+ attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale
15
+ attr_accessor :primary, :coder
16
+
17
+ alias :encoded? :coder
18
+
19
+ # Instantiates a new column in the table.
20
+ #
21
+ # +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int(11)</tt>.
22
+ # +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
23
+ # +sql_type+ is used to extract the column's length, if necessary. For example +60+ in
24
+ # <tt>company_name varchar(60)</tt>.
25
+ # It will be mapped to one of the standard Rails SQL types in the <tt>type</tt> attribute.
26
+ # +null+ determines if this column allows +NULL+ values.
27
+ def initialize(name, default, sql_type = nil, null = true)
28
+ @name = name
29
+ @sql_type = sql_type
30
+ @null = null
31
+ @limit = extract_limit(sql_type)
32
+ @precision = extract_precision(sql_type)
33
+ @scale = extract_scale(sql_type)
34
+ @type = simplified_type(sql_type)
35
+ @default = extract_default(default)
36
+ @primary = nil
37
+ @coder = nil
38
+ end
39
+
40
+ # Returns +true+ if the column is either of type string or text.
41
+ def text?
42
+ type == :string || type == :text
43
+ end
44
+
45
+ # Returns +true+ if the column is either of type integer, float or decimal.
46
+ def number?
47
+ type == :integer || type == :float || type == :decimal
48
+ end
49
+
50
+ def has_default?
51
+ !default.nil?
52
+ end
53
+
54
+ # Returns the Ruby class that corresponds to the abstract data type.
55
+ def klass
56
+ case type
57
+ when :integer then
58
+ Fixnum
59
+ when :float then
60
+ Float
61
+ when :decimal then
62
+ BigDecimal
63
+ when :datetime, :timestamp, :time then
64
+ Time
65
+ when :date then
66
+ Date
67
+ when :text, :string, :binary then
68
+ String
69
+ when :boolean then
70
+ Object
71
+ end
72
+ end
73
+
74
+ # Casts value (which is a String) to an appropriate instance.
75
+ def type_cast(value)
76
+ return nil if value.nil?
77
+ return coder.load(value) if encoded?
78
+ value
79
+ end
80
+
81
+ def extract_default(default)
82
+ type_cast(default)
83
+ end
84
+
85
+ private
86
+
87
+ def extract_limit(sql_type)
88
+ $1.to_i if sql_type =~ /\((.*)\)/
89
+ end
90
+
91
+ def extract_precision(sql_type)
92
+ $2.to_i if sql_type =~ /^(numeric|decimal|number)\((\d+)(,\d+)?\)/i
93
+ end
94
+
95
+ def extract_scale(sql_type)
96
+ case sql_type
97
+ when /^(numeric|decimal|number)\((\d+)\)/i then
98
+ 0
99
+ when /^(numeric|decimal|number)\((\d+)(,(\d+))\)/i then
100
+ $4.to_i
101
+ end
102
+ end
103
+
104
+ def simplified_type(field_type)
105
+ case field_type
106
+ when /int/i
107
+ :integer
108
+ when /float|double/i
109
+ :float
110
+ when /decimal|numeric|number/i
111
+ extract_scale(field_type) == 0 ? :integer : :decimal
112
+ when /datetime/i
113
+ :datetime
114
+ when /timestamp/i
115
+ :timestamp
116
+ when /time/i
117
+ :time
118
+ when /date/i
119
+ :date
120
+ when /clob/i, /text/i
121
+ :text
122
+ when /blob/i, /binary/i
123
+ :binary
124
+ when /char/i, /string/i
125
+ :string
126
+ when /boolean/i
127
+ :boolean
128
+ end
129
+ end
130
+ end
131
+ end
data/lib/nuodb/error.rb CHANGED
@@ -1,34 +1,6 @@
1
- #
2
- # Copyright (c) 2012, NuoDB, Inc.
3
- # All rights reserved.
4
- #
5
- # Redistribution and use in source and binary forms, with or without
6
- # modification, are permitted provided that the following conditions are met:
7
- #
8
- # * Redistributions of source code must retain the above copyright
9
- # notice, this list of conditions and the following disclaimer.
10
- # * Redistributions in binary form must reproduce the above copyright
11
- # notice, this list of conditions and the following disclaimer in the
12
- # documentation and/or other materials provided with the distribution.
13
- # * Neither the name of NuoDB, Inc. nor the names of its contributors may
14
- # be used to endorse or promote products derived from this software
15
- # without specific prior written permission.
16
- #
17
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
- # DISCLAIMED. IN NO EVENT SHALL NUODB, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
21
- # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
- # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
- # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25
- # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26
- # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
- #
28
-
29
1
  module NuoDB
30
2
 
31
- class Error < StandardError
3
+ class DatabaseError < StandardError
32
4
 
33
5
  attr_accessor :error_code
34
6
 
data/lib/nuodb/version.rb CHANGED
@@ -27,5 +27,5 @@
27
27
  #
28
28
 
29
29
  module NuoDB
30
- VERSION = '1.0.0.rc.1'
30
+ VERSION = '1.0.0.rc.2'
31
31
  end
data/nuodb.gemspec CHANGED
@@ -1,25 +1,33 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/nuodb/version', __FILE__)
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'nuodb/version'
3
5
 
4
- Gem::Specification.new do |gem|
5
- gem.name = 'nuodb'
6
- gem.version = NuoDB::VERSION
7
- gem.authors = %w('Robert Buck')
8
- gem.email = %w(support@nuodb.com)
9
- gem.description = %q{An easy to use database API for the NuoDB distributed database.}
10
- gem.summary = %q{Native Ruby driver for NuoDB.}
11
- gem.homepage = 'http://nuodb.github.com/ruby-nuodb/'
12
- gem.license = 'BSD'
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'nuodb'
8
+ spec.version = NuoDB::VERSION
9
+ spec.authors = ['Robert Buck']
10
+ spec.email = %w(support@nuodb.com)
11
+ spec.description = %q{An easy to use database API for the NuoDB distributed database.}
12
+ spec.summary = %q{Native Ruby driver for NuoDB.}
13
+ spec.homepage = 'http://nuodb.github.com/ruby-nuodb/'
14
+ spec.license = 'BSD'
13
15
 
14
- gem.rdoc_options = %w(--charset=UTF-8)
15
- gem.extra_rdoc_files = %w[README.rdoc]
16
+ spec.rdoc_options = %w(--charset=UTF-8)
17
+ spec.extra_rdoc_files = %w[AUTHORS README.rdoc LICENSE]
16
18
 
17
- gem.extensions = %w(ext/nuodb/extconf.rb)
19
+ spec.extensions = %w(ext/nuodb/extconf.rb)
18
20
 
19
- gem.add_development_dependency('rake', '~> 0.9')
20
- gem.add_development_dependency('rdoc', '~> 3.10')
21
+ spec.files = `git ls-files`.split($\)
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = %w(lib ext)
21
24
 
22
- gem.files = `git ls-files`.split($\)
23
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
24
- gem.require_paths = %w(lib ext)
25
+ spec.add_development_dependency('erubis', '~> 2.7.0')
26
+ spec.add_development_dependency('rake', '~> 0.9')
27
+ spec.add_development_dependency('rdoc', '~> 3.10')
28
+ spec.add_development_dependency('hanna-nouveau', '~> 0.2.4')
29
+
30
+ %w(rake rdoc simplecov hanna-nouveau rubydoc sdoc).each { |gem| spec.add_development_dependency gem }
31
+ %w(ruby-prof).each { |gem| spec.add_development_dependency gem }
32
+ %w(rspec rspec-core rspec-expectations rspec-mocks).each { |gem| spec.add_development_dependency gem, "~> 2.11.0" }
25
33
  end
File without changes
File without changes
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+ require 'nuodb'
3
+
4
+ describe NuoDB::Connection do
5
+ before do
6
+ end
7
+
8
+ after do
9
+ end
10
+
11
+ context "creating a connection" do
12
+
13
+ before(:each) do
14
+ end
15
+
16
+ after(:each) do
17
+ end
18
+
19
+ it "should raise an ArgumentError error when provided no configuration" do
20
+ lambda {
21
+ NuoDB::Connection.new
22
+ }.should raise_error(ArgumentError)
23
+ end
24
+
25
+ it "should raise an DatabaseError error when provided invalid credentials" do
26
+ lambda {
27
+ config = BaseTest.connection_config.clone
28
+ config[:password] = 'invalid'
29
+ NuoDB::Connection.new config do |connection|
30
+ connection.connected?.should be_true
31
+ end
32
+ }.should raise_error(NuoDB::DatabaseError)
33
+ end
34
+
35
+ #it "should permissibly support a code block after which the connection is automatically disconnected" do
36
+ # local_connection = nil
37
+ # NuoDB::Connection.new BaseTest.connection_config do |connection|
38
+ # connection.connected?.should be_true
39
+ # local_connection = connection # todo when real ref counting implementation is added
40
+ # end
41
+ # local_connection.connected?.should be_false
42
+ #end
43
+
44
+ # decision: we will not support this as we cannot guarantee that there are
45
+ # no outstanding references for the object, say for instance, the user
46
+ # passes a variable out of scope, and as the outer variable does not create
47
+ # a copy of the VALUE object (it is identical from what I see) there is no
48
+ # way to detect closure.
49
+ #
50
+ #it "should permissibly support a code block after which the connection is automatically disconnected even if an exception is raised" do
51
+ # @local_connection = nil
52
+ # lambda {
53
+ # NuoDB::Connection.new BaseTest.connection_config do |connection|
54
+ # connection.connected?.should be_true
55
+ # @local_connection = connection # todo when real ref counting implementation is added
56
+ # raise ArgumentError
57
+ # end
58
+ # }.should raise_error(ArgumentError)
59
+ # @local_connection.connected?.should be_false
60
+ #end
61
+
62
+ end
63
+
64
+ context "active connections" do
65
+
66
+ before(:each) do
67
+ @connection = BaseTest.connect
68
+ end
69
+
70
+ after(:each) do
71
+ #@connection.disconnect
72
+ @connection = nil
73
+ end
74
+
75
+ it "should yield true when connected? is called" do
76
+ @connection.connected?.should be_true
77
+ end
78
+
79
+ it "should yield true when ping is called" do
80
+ @connection.ping.should be_true
81
+ end
82
+
83
+ it "support configuring autocommit at the connection level" do
84
+ @connection.autocommit = true
85
+ @connection.autocommit?.should be_true
86
+
87
+ @connection.autocommit = false
88
+ @connection.autocommit?.should be_false
89
+ end
90
+
91
+ end
92
+
93
+ #context "inactive connections" do
94
+ #
95
+ # before(:each) do
96
+ # @connection = BaseTest.connect
97
+ # @connection.disconnect # todo when real ref counting implementation is added
98
+ # end
99
+ #
100
+ # after(:each) do
101
+ # @connection = nil
102
+ # end
103
+ #
104
+ # it "should yield false when connected? is called" do
105
+ # @connection.connected?.should be_false
106
+ # end
107
+ #
108
+ #end
109
+
110
+ end
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+ require 'nuodb'
3
+ require 'bigdecimal'
4
+
5
+ describe NuoDB::Result do
6
+
7
+ attr_reader :connection
8
+
9
+ before(:all) do
10
+ @connection = BaseTest.connect
11
+ end
12
+
13
+ after(:all) do
14
+ end
15
+
16
+ context "nuodb naturally handles ruby datatypes" do
17
+
18
+ attr_reader :statement
19
+ attr_reader :prepared_statement
20
+ attr_accessor :data_array
21
+
22
+ make_type_table_ddl = 'CREATE TABLE test_datatypes (f1 BOOLEAN, f2 DOUBLE, f3 INTEGER, f4 BIGINT, f5 STRING, f6 DATE, f7 TIMESTAMP)' #, f8 NUMERIC)'
23
+ drop_type_table_ddl = "DROP TABLE IF EXISTS test_datatypes"
24
+ insert_dml = "insert into test_datatypes(f1, f2, f3, f4, f5, f6, f7) values(?, ?, ?, ?, ?, ?, ?)" # , f8) later, ", ?)"
25
+ select_dml = "select * from test_datatypes"
26
+ delete_dml = "delete from test_datatypes"
27
+
28
+ machine_bytes = %w(foo).pack('p').size
29
+ machine_bits = machine_bytes * 8
30
+ machine_max_signed = 2**(machine_bits-1) - 1
31
+ machine_max_unsigned = 2**machine_bits - 1
32
+ machine_min_signed = -(2**(machine_bits-1))
33
+ machine_min_unsigned = -(2**machine_bits)
34
+ machine_bits_32 = 32
35
+ machine_max_signed_32 = 2**(machine_bits_32-1) - 1
36
+ machine_max_unsigned_32 = 2**machine_bits_32 - 1
37
+ machine_min_signed_32 = -(2**(machine_bits_32-1))
38
+ machine_min_unsigned_32 = -(2**machine_bits_32)
39
+
40
+ before(:all) do
41
+ @data_array = [
42
+ [false, 12345.67890, -1, 222222222, 'Bofur and Bifur', Date.new(1957, 3, 27), Time.new], #, BigDecimal("1000234000567.95")],
43
+ [false, -12345.67890, -1, -222222222, 'Bofur and Bifur', Date.new(1957, 3, 27), Time.new], #, BigDecimal("-1000234000567.95")],
44
+ [false, -0.0, -0, -0, 'Kili and Fili', Date.new(2001, 12, 3), Time.new], #, BigDecimal("-0.0")],
45
+ [true, +0.0, +0, +0, 'Kili and Fili', Date.new(2001, 12, 3), Time.new], #, BigDecimal("+0.0")],
46
+ [false, -1.0, -1, -1, 'Kili and Fili', Date.new(2001, 12, 3), Time.new], #, BigDecimal("-1.0")],
47
+ [true, +1.0, +1, -1, 'Kili and Fili', Date.new(2001, 12, 3), Time.new], #, BigDecimal("+1.0")],
48
+ [false, (1.0 * machine_min_signed_32), machine_min_signed_32, machine_min_signed, 'Kili and Fili', Date.new(2001, 12, 3), Time.new], #, BigDecimal("-1.0")],
49
+ [true, (1.0 * machine_max_signed_32), machine_max_signed_32, machine_max_signed, 'Kili and Fili', Date.new(2001, 12, 3), Time.new], #, BigDecimal("-1.0")],
50
+ [false, (1.0 * machine_min_signed_32), machine_min_signed_32, machine_max_unsigned_32, 'Kili and Fili', Date.new(2001, 12, 3), Time.new], #, BigDecimal("-1.0")],
51
+ [true, (1.0 * machine_max_signed_32), machine_max_signed_32, machine_min_unsigned_32, 'Kili and Fili', Date.new(2001, 12, 3), Time.new], #, BigDecimal("-1.0")],
52
+ [false, (1.0 * machine_min_signed_32), machine_min_signed_32, machine_max_unsigned_32, 'Kili and Fili', Date.new(2001, 12, 3), Time.new], #, BigDecimal("#{machine_max_unsigned}")],
53
+ [true, (1.0 * machine_max_signed_32), machine_max_signed_32, machine_min_unsigned_32, 'Kili and Fili', Date.new(2001, 12, 3), Time.new], #, BigDecimal("#{machine_min_unsigned}")],
54
+ ]
55
+ [-1, 1].each do |sign|
56
+ random = Random.new(Random.new_seed)
57
+ data_array << [rand(2).zero?, sign * random.rand(1.0 * machine_max_signed_32), random.rand(machine_max_signed_32),
58
+ random.rand(machine_max_signed), 'Kili and Fili', Date.new(2001, 12, 3), Time.new] #, BigDecimal("-1.0")
59
+ end
60
+ end
61
+
62
+ before(:each) do
63
+ @statement = @connection.statement
64
+ statement.execute(drop_type_table_ddl)
65
+ statement.execute(make_type_table_ddl)
66
+ @prepared_statement = connection.prepare insert_dml
67
+ end
68
+
69
+ after(:each) do
70
+ statement.execute(drop_type_table_ddl)
71
+ end
72
+
73
+ # n.b. product defect, set this to false when it is fixed; no numeric support
74
+ jira_db_2288_is_open = true
75
+
76
+ it "input data types are be matched with output data types" do
77
+ data_array.each do |binds|
78
+ statement.execute(delete_dml).should be_false
79
+ prepared_statement.bind_params binds
80
+ prepared_statement.execute.should be_false
81
+ statement.execute(select_dml).should be_true
82
+ statement.results.rows.each do |row|
83
+ row[0].should eql(binds[0])
84
+ row[1].should be_within(0.001).of(binds[1])
85
+ row[2].should eql(binds[2])
86
+ row[3].should eql(binds[3])
87
+ row[4].should eql(binds[4])
88
+ row[5].should be_within(1).of(binds[5])
89
+ row[6].should be_within(1).of(binds[6])
90
+ #row[7].should eql(binds[7]) unless jira_db_2288_is_open
91
+
92
+ row.each_with_index do |data, idx|
93
+ #unless idx == 7 and jira_db_2288_is_open
94
+ data.should be_a(binds[idx].class)
95
+ #end
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ it "string input data types are be matched with type-specific output data types" do
102
+ data_array.each do |binds|
103
+ statement.execute(delete_dml).should be_false
104
+ string_binds = binds.each_with_index.inject([]) do |array, (bind, index)|
105
+ if [6].include? index
106
+ array << bind.getutc
107
+ else
108
+ array << bind.to_s
109
+ end
110
+ end
111
+ prepared_statement.bind_params string_binds
112
+ prepared_statement.execute.should be_false
113
+ statement.execute(select_dml).should be_true
114
+ statement.results.rows.each do |row|
115
+ row[0].should eql(binds[0])
116
+ row[1].should be_within(0.001).of(binds[1])
117
+ row[2].should eql(binds[2])
118
+ row[3].should eql(binds[3])
119
+ row[4].should eql(binds[4])
120
+ row[5].should be_within(1).of(binds[5])
121
+ row[6].should be_within(1).of(binds[6])
122
+ #row[7].should eql(binds[7]) unless jira_db_2288_is_open
123
+
124
+ row.each_with_index do |data, idx|
125
+ #unless idx == 7 and jira_db_2288_is_open
126
+ data.should be_a(binds[idx].class)
127
+ #end
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ end
134
+
135
+ #context "nuodb naturally handles ruby date/time conversions" do
136
+ #
137
+ # it "preserves time objects with local_time conversion to default timezone utc" do
138
+ # with_env_tz 'America/New_York' do
139
+ # with_default_timezone :utc do
140
+ # time = Time.local(2000)
141
+ # #topic = Topic.create('written_on' => time)
142
+ # #saved_time = Topic.find(topic.id).reload.written_on
143
+ # #assert_equal time, saved_time
144
+ # #assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "EST"], time.to_a
145
+ # #assert_equal [0, 0, 5, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
146
+ # end
147
+ # end
148
+ # end
149
+ #
150
+ # it "preserves time objects with time with zone conversion to default timezone utc" do
151
+ # with_env_tz 'America/New_York' do
152
+ # with_default_timezone :utc do
153
+ # Time.use_zone 'Central Time (US & Canada)' do
154
+ # time = Time.zone.local(2000)
155
+ # #topic = Topic.create('written_on' => time)
156
+ # #saved_time = Topic.find(topic.id).reload.written_on
157
+ # #assert_equal time, saved_time
158
+ # #assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "CST"], time.to_a
159
+ # #assert_equal [0, 0, 6, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
160
+ # end
161
+ # end
162
+ # end
163
+ # end
164
+ #end
165
+ end