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.
- data/.gitignore +4 -1
- data/.rspec +2 -0
- data/AUTHORS +2 -2
- data/Gemfile +1 -5
- data/LICENSE +8 -9
- data/README.rdoc +21 -22
- data/Rakefile +42 -13
- data/ext/nuodb/atomic.c +11 -0
- data/ext/nuodb/atomic.h +62 -0
- data/ext/nuodb/extconf.rb +22 -1
- data/ext/nuodb/nuodb.cpp +2140 -753
- data/lib/nuodb/column.rb +131 -0
- data/lib/nuodb/error.rb +1 -29
- data/lib/nuodb/version.rb +1 -1
- data/nuodb.gemspec +26 -18
- data/spec/data/.gitignore +0 -0
- data/spec/functional/column_spec.rb +0 -0
- data/spec/functional/connection_spec.rb +110 -0
- data/spec/functional/datatypes_spec.rb +165 -0
- data/spec/functional/generated_keys_spec.rb +137 -0
- data/spec/functional/prepared_statement_spec.rb +160 -0
- data/spec/functional/statement_spec.rb +200 -0
- data/spec/functional/transaction_spec.rb +0 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/config.rb +42 -0
- data/spec/support/config.yml +10 -0
- data/spec/support/connection.rb +15 -0
- data/spec/support/datetime.rb +25 -0
- data/spec/unit/.gitignore +0 -0
- data/tasks/rdoc.rb +19 -0
- data/tasks/rspec.rb +56 -0
- data/tasks/stats.rb +24 -0
- metadata +253 -8
- data/COPYING +0 -25
- data/test/test_nuodb.rb +0 -267
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nuodb'
|
3
|
+
|
4
|
+
describe NuoDB::Statement do
|
5
|
+
|
6
|
+
attr_reader :connection
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
@connection = BaseTest.connect
|
10
|
+
end
|
11
|
+
|
12
|
+
check_drop_table_ddl = 'DROP TABLE CASCADE IF EXISTS test_generated_keys'
|
13
|
+
|
14
|
+
after(:all) do
|
15
|
+
end
|
16
|
+
|
17
|
+
context "inserting with always generated keys" do
|
18
|
+
|
19
|
+
create_table_ddl = 'CREATE TABLE test_generated_keys (id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, data INTEGER DEFAULT (5) NOT NULL);'
|
20
|
+
|
21
|
+
attr_reader :statement
|
22
|
+
|
23
|
+
before(:each) do
|
24
|
+
@statement = @connection.statement
|
25
|
+
statement.execute(check_drop_table_ddl)
|
26
|
+
statement.execute(create_table_ddl)
|
27
|
+
(1..10).each do |value|
|
28
|
+
statement.execute "INSERT INTO test_generated_keys (data) VALUES (#{value})"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
after(:each) do
|
33
|
+
statement.execute(check_drop_table_ddl)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should raise an error when attempting to provide your own key" do
|
37
|
+
lambda {
|
38
|
+
statement.execute("INSERT INTO test_generated_keys (id, data) VALUES (1,5)")
|
39
|
+
}.should raise_error(NuoDB::DatabaseError, /can't assign a value to generated always identity/)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "generated_keys should return the most recently created generated key" do
|
43
|
+
statement.execute("SELECT * FROM test_generated_keys").should be_true
|
44
|
+
value_results = statement.results
|
45
|
+
value_rows = value_results.rows
|
46
|
+
value_rows.length.should eql(10)
|
47
|
+
last_generated_id = value_rows.last[0]
|
48
|
+
prev_generated_id = nil
|
49
|
+
(1..10).each do |value|
|
50
|
+
statement.execute("INSERT INTO test_generated_keys (data) VALUES (#{value})").should be_false
|
51
|
+
keys_results = statement.generated_keys
|
52
|
+
keys_rows = keys_results.rows
|
53
|
+
keys_results.rows.should eql(keys_rows)
|
54
|
+
keys_rows.length.should eql(1)
|
55
|
+
keys_rows.last[0].should_not eql(last_generated_id)
|
56
|
+
keys_rows.last[0].should_not eql(prev_generated_id)
|
57
|
+
prev_generated_id = keys_rows.last[0]
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
context "inserting with default generated keys" do
|
65
|
+
|
66
|
+
create_table_ddl = 'CREATE TABLE test_generated_keys (id INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, data INTEGER DEFAULT (5) NOT NULL);'
|
67
|
+
|
68
|
+
attr_reader :statement
|
69
|
+
|
70
|
+
before(:each) do
|
71
|
+
@statement = @connection.statement
|
72
|
+
statement.execute(check_drop_table_ddl)
|
73
|
+
statement.execute(create_table_ddl)
|
74
|
+
(1..10).each do |value|
|
75
|
+
statement.execute "INSERT INTO test_generated_keys (data) VALUES (#{value})"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
after(:each) do
|
80
|
+
statement.execute(check_drop_table_ddl)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should not raise an error when attempting to provide your own key" do
|
84
|
+
lambda {
|
85
|
+
statement.execute("INSERT INTO test_generated_keys (id, data) VALUES (1,5)")
|
86
|
+
}.should_not raise_error(NuoDB::DatabaseError, /can't assign a value to generated always identity/)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should raise an error when attempting to provide your own key and its a dupe" do
|
90
|
+
statement.execute("INSERT INTO test_generated_keys (id, data) VALUES (1,5)")
|
91
|
+
lambda {
|
92
|
+
statement.execute("INSERT INTO test_generated_keys (id, data) VALUES (1,5)")
|
93
|
+
}.should_not raise_error(NuoDB::DatabaseError, /can't assign a value to generated always identity/)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "generated_keys should return the most recently created generated key" do
|
97
|
+
statement.execute("SELECT * FROM test_generated_keys").should be_true
|
98
|
+
value_results = statement.results
|
99
|
+
value_rows = value_results.rows
|
100
|
+
value_rows.length.should eql(10)
|
101
|
+
last_generated_id = value_rows.last[0]
|
102
|
+
prev_generated_id = nil
|
103
|
+
(1..10).each do |value|
|
104
|
+
statement.execute("INSERT INTO test_generated_keys (data) VALUES (#{value})").should be_false
|
105
|
+
keys_results = statement.generated_keys
|
106
|
+
keys_rows = keys_results.rows
|
107
|
+
keys_rows.length.should eql(1)
|
108
|
+
keys_rows.last[0].should_not eql(last_generated_id)
|
109
|
+
keys_rows.last[0].should_not eql(prev_generated_id)
|
110
|
+
prev_generated_id = keys_rows.last[0]
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
it "generated_keys should skip manually provided ones" do
|
116
|
+
statement.execute("INSERT INTO test_generated_keys (id, data) VALUES (2500,5)")
|
117
|
+
statement.execute("SELECT * FROM test_generated_keys").should be_true
|
118
|
+
value_results = statement.results
|
119
|
+
value_rows = value_results.rows
|
120
|
+
value_rows.length.should eql(11)
|
121
|
+
last_generated_id = value_rows.last[0]
|
122
|
+
prev_generated_id = nil
|
123
|
+
(1..1000).each do |value|
|
124
|
+
statement.execute("INSERT INTO test_generated_keys (data) VALUES (#{value})").should be_false
|
125
|
+
keys_results = statement.generated_keys
|
126
|
+
keys_rows = keys_results.rows
|
127
|
+
keys_rows.length.should eql(1)
|
128
|
+
keys_rows.last[0].should_not eql(last_generated_id)
|
129
|
+
keys_rows.last[0].should_not eql(prev_generated_id)
|
130
|
+
prev_generated_id = keys_rows.last[0]
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nuodb'
|
3
|
+
|
4
|
+
describe NuoDB::PreparedStatement do
|
5
|
+
before(:all) do
|
6
|
+
@connection = BaseTest.connect
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table_all_types_ddl = 'create table TEST_TYPES (f0 SMALLINT, f1 INTEGER, f2 BIGINT, f3 STRING, f4 VARCHAR, f5 LONGVARCHAR, f6 TIME, f7 DATE, f8 TIMESTAMP)'
|
10
|
+
|
11
|
+
after(:all) do
|
12
|
+
#@connection.disconnect
|
13
|
+
end
|
14
|
+
|
15
|
+
context "creating a prepared statement" do
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
end
|
19
|
+
|
20
|
+
after(:each) do
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should raise an ArgumentError error when provided no sql" do
|
24
|
+
lambda {
|
25
|
+
@connection.prepare
|
26
|
+
}.should raise_error(ArgumentError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should raise an TypeError error when a string is not provided as an argument" do
|
30
|
+
lambda {
|
31
|
+
@connection.prepare nil
|
32
|
+
}.should raise_error(TypeError)
|
33
|
+
end
|
34
|
+
|
35
|
+
#it "should permissibly support a code block after which the prepared statement is automatically finished" do
|
36
|
+
# local_statement = nil
|
37
|
+
# @connection.prepare 'select 1 from dual' do |statement|
|
38
|
+
# statement.count.should eq(-1)
|
39
|
+
# local_statement = statement
|
40
|
+
# end
|
41
|
+
# lambda {
|
42
|
+
# local_statement.count
|
43
|
+
# }.should raise_error(ArgumentError)
|
44
|
+
#end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
context "creating tables" do
|
49
|
+
|
50
|
+
before(:each) do
|
51
|
+
end
|
52
|
+
|
53
|
+
after(:each) do
|
54
|
+
@connection.prepare 'drop table if exists TEST_TYPES' do |statement|
|
55
|
+
statement.execute.should be_false
|
56
|
+
end
|
57
|
+
|
58
|
+
it "using a prepared statement should return false upon execute" do
|
59
|
+
@connection.prepare create_table_all_types_ddl do |statement|
|
60
|
+
statement.execute.should be_false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should raise a database error if trying to create a table that already exists" do
|
65
|
+
@connection.prepare create_table_all_types_ddl do |statement|
|
66
|
+
statement.execute.should be_false
|
67
|
+
lambda {
|
68
|
+
statement.execute
|
69
|
+
}.should raise_error(NuoDB::DatabaseError)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "deleting tables" do
|
78
|
+
|
79
|
+
before(:each) do
|
80
|
+
end
|
81
|
+
|
82
|
+
after(:each) do
|
83
|
+
end
|
84
|
+
|
85
|
+
it "using a prepared statement should return false upon execute" do
|
86
|
+
@connection.prepare 'drop table if exists TEST_TYPES' do |statement|
|
87
|
+
statement.execute.should be_false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should raise a database exception if the table does not exist and 'if exists' is not used" do
|
92
|
+
lambda {
|
93
|
+
@connection.prepare 'drop table NO_EXIST' do |statement|
|
94
|
+
statement.execute.should be_false
|
95
|
+
end
|
96
|
+
}.should raise_error(NuoDB::DatabaseError)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
context "inserting into tables" do
|
102
|
+
|
103
|
+
insert_ddl = "create table TEST_TYPES (f1 INTEGER, f2 DOUBLE, f3 STRING, f4 DATE, f5 TIME);"
|
104
|
+
drop_table = "drop table if exists TEST_TYPES"
|
105
|
+
insert_dml = "insert into test_types(f1, f2, f3, f4, f5) values(?, ?, ?, ?, ?)"
|
106
|
+
select_dml = "select * from test_types"
|
107
|
+
|
108
|
+
before(:each) do
|
109
|
+
@connection.prepare insert_ddl do |statement|
|
110
|
+
statement.execute.should be_false
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
after(:each) do
|
115
|
+
@connection.prepare drop_table do |statement|
|
116
|
+
statement.execute.should be_false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
it "using a prepared statement should return false upon execute" do
|
121
|
+
@connection.prepare insert_dml do |statement|
|
122
|
+
date = Date.new(2001, 12, 3)
|
123
|
+
time = Time.new
|
124
|
+
statement.bind_params([56, 6.7, "String", date, time])
|
125
|
+
statement.execute.should be_false
|
126
|
+
@connection.prepare select_dml do |select|
|
127
|
+
select.execute.should be_true
|
128
|
+
select.results.each do |row|
|
129
|
+
row[0].should eql(56)
|
130
|
+
row[1].should eql(6.7)
|
131
|
+
row[2].should eql("String")
|
132
|
+
row[3].should eql(date)
|
133
|
+
row[4].should be_within(1).of(time)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
context "executing a prepared statement" do
|
142
|
+
|
143
|
+
before(:each) do
|
144
|
+
end
|
145
|
+
|
146
|
+
after(:each) do
|
147
|
+
end
|
148
|
+
|
149
|
+
#it "should return a single row result set for select 1 from dual" do
|
150
|
+
# @connection.prepare 'select 1 from dual' do |statement|
|
151
|
+
# statement.execute.should be_true
|
152
|
+
# results = statement.results
|
153
|
+
# results.finish
|
154
|
+
# results.should_not be_nil
|
155
|
+
# end
|
156
|
+
#end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nuodb'
|
3
|
+
|
4
|
+
describe NuoDB::Statement do
|
5
|
+
before(:all) do
|
6
|
+
@connection = BaseTest.connect
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table_all_types_ddl = 'create table TEST_TYPES (f1 INTEGER DEFAULT 4, f2 DOUBLE NOT NULL, f3 STRING, f4 DATE, f5 TIME);'
|
10
|
+
check_drop_table_all_types_ddl = 'drop table if exists TEST_TYPES'
|
11
|
+
drop_table_all_types_ddl = 'drop table NO_EXIST'
|
12
|
+
check_drop_table_all_types_ddl = 'drop table if exists TEST_TYPES'
|
13
|
+
|
14
|
+
after(:all) do
|
15
|
+
#@connection.disconnect
|
16
|
+
end
|
17
|
+
|
18
|
+
context "creating a statement" do
|
19
|
+
|
20
|
+
before(:each) do
|
21
|
+
end
|
22
|
+
|
23
|
+
after(:each) do
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should not raise an error when created" do
|
27
|
+
lambda {
|
28
|
+
@connection.statement
|
29
|
+
}.should_not raise_error
|
30
|
+
end
|
31
|
+
|
32
|
+
#it "should permissibly support a code block after which the statement is automatically finished" do
|
33
|
+
# local_statement = nil
|
34
|
+
# @connection.statement do |statement|
|
35
|
+
# statement.execute('select 1 from dual').should be_true
|
36
|
+
# local_statement = statement # todo when real ref counting implementation is added
|
37
|
+
# end
|
38
|
+
# lambda {
|
39
|
+
# local_statement.count
|
40
|
+
# }.should raise_error(ArgumentError)
|
41
|
+
#end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
context "creating tables" do
|
46
|
+
|
47
|
+
before(:each) do
|
48
|
+
end
|
49
|
+
|
50
|
+
after(:each) do
|
51
|
+
@connection.statement do |statement|
|
52
|
+
statement.execute(drop_table_all_types_ddl).should be_false
|
53
|
+
end
|
54
|
+
|
55
|
+
it "using a statement should return false upon execute" do
|
56
|
+
@connection.statement do |statement|
|
57
|
+
statement.execute(create_table_all_types_ddl).should be_false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should raise a database error if trying to create a table that already exists" do
|
62
|
+
@connection.statement do |statement|
|
63
|
+
statement.execute(create_table_all_types_ddl).should be_false
|
64
|
+
lambda {
|
65
|
+
statement.execute
|
66
|
+
}.should raise_error(NuoDB::DatabaseError)
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "deleting tables" do
|
75
|
+
|
76
|
+
before(:each) do
|
77
|
+
end
|
78
|
+
|
79
|
+
after(:each) do
|
80
|
+
end
|
81
|
+
|
82
|
+
it "using a statement should return false upon execute" do
|
83
|
+
@connection.statement do |statement|
|
84
|
+
statement.execute(check_drop_table_all_types_ddl).should be_false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should raise a database exception if the table does not exist and 'if exists' is not used" do
|
89
|
+
lambda {
|
90
|
+
@connection.statement do |statement|
|
91
|
+
statement.execute(drop_table_all_types_ddl).should be_false
|
92
|
+
end
|
93
|
+
}.should raise_error(NuoDB::DatabaseError)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
context "inserting into tables" do
|
99
|
+
|
100
|
+
insert_dml = "insert into test_types(f1, f2, f3, f4, f5) values(?, ?, ?, ?, ?)"
|
101
|
+
select_dml = "select * from test_types"
|
102
|
+
|
103
|
+
before(:each) do
|
104
|
+
@connection.statement do |statement|
|
105
|
+
statement.execute(create_table_all_types_ddl).should be_false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
after(:each) do
|
110
|
+
#@connection.statement do |statement|
|
111
|
+
# statement.execute(check_drop_table_all_types_ddl).should be_false
|
112
|
+
#end
|
113
|
+
end
|
114
|
+
|
115
|
+
it "using a statement should return false upon execute" do
|
116
|
+
@connection.prepare insert_dml do |statement|
|
117
|
+
date = Date.new(2001, 12, 3)
|
118
|
+
time = Time.new
|
119
|
+
statement.bind_params([56, 6.7, "String", date, time])
|
120
|
+
statement.execute.should be_false
|
121
|
+
@connection.statement do |select|
|
122
|
+
select.execute(select_dml).should be_true
|
123
|
+
results = select.results
|
124
|
+
results.each do |row|
|
125
|
+
row[0].should eql(56)
|
126
|
+
row[1].should eql(6.7)
|
127
|
+
row[2].should eql("String")
|
128
|
+
row[3].should eql(date)
|
129
|
+
row[4].should be_within(1).of(time)
|
130
|
+
end
|
131
|
+
columns = results.columns
|
132
|
+
results.columns.should eql(columns)
|
133
|
+
|
134
|
+
columns[0].name.should eql("F1")
|
135
|
+
columns[1].name.should eql("F2")
|
136
|
+
columns[2].name.should eql("F3")
|
137
|
+
columns[3].name.should eql("F4")
|
138
|
+
columns[4].name.should eql("F5")
|
139
|
+
|
140
|
+
columns[0].type.should eql(:integer)
|
141
|
+
columns[1].type.should eql(:float)
|
142
|
+
columns[2].type.should eql(:string)
|
143
|
+
columns[3].type.should eql(:date)
|
144
|
+
columns[4].type.should eql(:time)
|
145
|
+
|
146
|
+
columns[0].default.should eql(4)
|
147
|
+
columns[1].default.should be_nil
|
148
|
+
columns[2].default.should be_nil
|
149
|
+
columns[3].default.should be_nil
|
150
|
+
columns[4].default.should be_nil
|
151
|
+
|
152
|
+
columns[0].null.should be_true
|
153
|
+
columns[1].null.should be_false
|
154
|
+
columns[2].null.should be_true
|
155
|
+
columns[3].null.should be_true
|
156
|
+
columns[4].null.should be_true
|
157
|
+
|
158
|
+
columns.each do |column|
|
159
|
+
column.name.should_not be_nil
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
# TODO BEGIN
|
168
|
+
|
169
|
+
# Unsure if this should pass or not; an outstanding question was sent to MJ and John
|
170
|
+
# about the intended behavior.
|
171
|
+
|
172
|
+
#context "executing a prepared statement" do
|
173
|
+
#
|
174
|
+
# insert_dml = "insert into test_types(f1, f2, f3, f4, f5) values(?, ?, ?, ?, ?)"
|
175
|
+
#
|
176
|
+
# before(:each) do
|
177
|
+
# @connection.statement do |statement|
|
178
|
+
# statement.execute(create_table_all_types_ddl).should be_false
|
179
|
+
# end
|
180
|
+
# end
|
181
|
+
#
|
182
|
+
# after(:each) do
|
183
|
+
# #@connection.statement do |statement|
|
184
|
+
# # statement.execute(check_drop_table_all_types_ddl).should be_false
|
185
|
+
# #end
|
186
|
+
# end
|
187
|
+
#
|
188
|
+
# it "should return a single row result set for select 1 from dual" do
|
189
|
+
# @connection.statement do |statement|
|
190
|
+
# statement.execute(insert_dml).should be_true
|
191
|
+
# results = statement.results
|
192
|
+
# #results.should_not be_nil
|
193
|
+
# end
|
194
|
+
# end
|
195
|
+
#
|
196
|
+
#end
|
197
|
+
|
198
|
+
# TODO END
|
199
|
+
|
200
|
+
end
|