dm-oracle-adapter 1.0.0.rc1

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 ADDED
@@ -0,0 +1,36 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## Rubinius
17
+ *.rbc
18
+
19
+ ## PROJECT::GENERAL
20
+ *.gem
21
+ coverage
22
+ rdoc
23
+ pkg
24
+ tmp
25
+ doc
26
+ log
27
+ .yardoc
28
+ measurements
29
+
30
+ ## BUNDLER
31
+ .bundle
32
+ Gemfile.local
33
+ Gemfile.lock
34
+
35
+ ## PROJECT::SPECIFIC
36
+ spec/db/
data/Gemfile ADDED
@@ -0,0 +1,87 @@
1
+ # If you're working on more than one datamapper gem at a time, then it's
2
+ # recommended to create a local Gemfile and use this instead of the git
3
+ # sources. This will make sure that you are developing against your
4
+ # other local datamapper sources that you currently work on. Gemfile.local
5
+ # will behave identically to the standard Gemfile apart from the fact that
6
+ # it fetches the gems from local paths. This means that you can use the
7
+ # same environment variables, like ADAPTER when running bundle commands.
8
+ # Gemfile.local is added to .gitignore, so you don't need to worry about
9
+ # accidentally checking local development paths into git.
10
+ #
11
+ # bundle exec rake local_gemfile
12
+ #
13
+ # will give you a Gemfile.local file that points to your local clones of
14
+ # the various datamapper gems. It's assumed that all datamapper repo clones
15
+ # reside in the same directory. You can use the Gemfile.local like so for
16
+ # running any bundle command:
17
+ #
18
+ # BUNDLE_GEMFILE=Gemfile.local bundle foo
19
+ #
20
+ # To speed up running bundle tasks, it's recommended to run
21
+ #
22
+ # bundle lock
23
+ #
24
+ # after running 'bundle install' for the first time. This will make 'bundle exec' run
25
+ # a lot faster compared to the unlocked version. With an unlocked bundle you would
26
+ # typically just run 'bundle install' from time to time to fetch the latest sources from
27
+ # upstream. When you locked your bundle, you need to run
28
+ #
29
+ # bundle install --relock
30
+ #
31
+ # to make sure to fetch the latest updates and then lock the bundle again. Gemfile.lock
32
+ # is added to the .gitignore file, so you don't need to worry about accidentally checking
33
+ # it into version control.
34
+
35
+ source 'http://rubygems.org'
36
+
37
+ DATAMAPPER = 'git://github.com/datamapper'
38
+ DM_VERSION = '~> 1.0.0.rc1'
39
+ DO_VERSION = '~> 0.10.2'
40
+
41
+ group :runtime do # Runtime dependencies (as in the gemspec)
42
+
43
+ gem 'do_oracle', DO_VERSION, :git => "#{DATAMAPPER}/do.git"
44
+ gem 'dm-do-adapter', DM_VERSION, :git => "#{DATAMAPPER}/dm-do-adapter.git"
45
+
46
+ end
47
+
48
+ group(:development) do # Development dependencies (as in the gemspec)
49
+
50
+ gem 'dm-migrations', DM_VERSION, :git => "#{DATAMAPPER}/dm-migrations.git"
51
+
52
+ gem 'rake', '~> 0.8.7'
53
+ gem 'rspec', '~> 1.3'
54
+ gem 'jeweler', '~> 1.4'
55
+
56
+ end
57
+
58
+ group :datamapper do # We need this because we want to pin these dependencies to their git master sources
59
+
60
+ if ENV['EXTLIB']
61
+ gem 'extlib', '~> 0.9.15', :git => "#{DATAMAPPER}/extlib.git", :require => nil
62
+ else
63
+ gem 'activesupport', '~> 3.0.0.beta3', :git => 'git://github.com/rails/rails.git', :require => nil
64
+ end
65
+
66
+ gem 'dm-core', DM_VERSION, :git => "#{DATAMAPPER}/dm-core.git"
67
+ gem 'data_objects', DO_VERSION, :git => "#{DATAMAPPER}/do.git"
68
+
69
+ plugins = ENV['PLUGINS'] || ENV['PLUGIN']
70
+ plugins = (plugins.to_s.gsub(',',' ').split(' ') + ['dm-migrations']).uniq
71
+
72
+ plugins.each do |plugin|
73
+ gem plugin, DM_VERSION, :git => "#{DATAMAPPER}/#{plugin}.git"
74
+ end
75
+
76
+ end
77
+
78
+ group :quality do # These gems contain rake tasks that check the quality of the source code
79
+
80
+ gem 'metric_fu', '~> 1.3'
81
+ gem 'rcov', '~> 0.9.7'
82
+ gem 'reek', '~> 1.2.7'
83
+ gem 'roodi', '~> 2.1'
84
+ gem 'yard', '~> 0.5'
85
+ gem 'yardstick', '~> 0.1'
86
+
87
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Dan Kubb
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+
6
+ require 'jeweler'
7
+
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = 'dm-oracle-adapter'
10
+ gem.summary = 'Oracle Adapter for DataMapper'
11
+ gem.description = gem.summary
12
+ gem.authors = ["Dan Kubb"]
13
+ gem.email = %q{dan.kubb@gmail.com}
14
+ gem.homepage = 'http://github.com/datamapper/dm-oracle-adapter'
15
+
16
+ gem.add_dependency 'do_oracle', '~> 0.10.1'
17
+ gem.add_dependency 'dm-do-adapter', '~> 1.0.0.rc1'
18
+
19
+ gem.add_development_dependency 'rspec', '~> 1.3'
20
+ end
21
+
22
+ Jeweler::GemcutterTasks.new
23
+
24
+ FileList['tasks/**/*.rake'].each { |task| import task }
25
+ rescue LoadError
26
+ puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler'
27
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0.rc1
@@ -0,0 +1,66 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{dm-oracle-adapter}
8
+ s.version = "1.0.0.rc1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Dan Kubb"]
12
+ s.date = %q{2010-05-19}
13
+ s.description = %q{Oracle Adapter for DataMapper}
14
+ s.email = %q{dan.kubb@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "Gemfile",
21
+ "LICENSE",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "dm-oracle-adapter.gemspec",
25
+ "lib/dm-oracle-adapter.rb",
26
+ "lib/dm-oracle-adapter/adapter.rb",
27
+ "lib/dm-oracle-adapter/spec/setup.rb",
28
+ "spec/adapter_spec.rb",
29
+ "spec/rcov.opts",
30
+ "spec/spec.opts",
31
+ "spec/spec_helper.rb",
32
+ "tasks/local_gemfile.rake",
33
+ "tasks/spec.rake",
34
+ "tasks/yard.rake",
35
+ "tasks/yardstick.rake"
36
+ ]
37
+ s.homepage = %q{http://github.com/datamapper/dm-oracle-adapter}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.6}
41
+ s.summary = %q{Oracle Adapter for DataMapper}
42
+ s.test_files = [
43
+ "spec/adapter_spec.rb",
44
+ "spec/spec_helper.rb"
45
+ ]
46
+
47
+ if s.respond_to? :specification_version then
48
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
52
+ s.add_runtime_dependency(%q<do_oracle>, ["~> 0.10.1"])
53
+ s.add_runtime_dependency(%q<dm-do-adapter>, ["~> 1.0.0.rc1"])
54
+ s.add_development_dependency(%q<rspec>, ["~> 1.3"])
55
+ else
56
+ s.add_dependency(%q<do_oracle>, ["~> 0.10.1"])
57
+ s.add_dependency(%q<dm-do-adapter>, ["~> 1.0.0.rc1"])
58
+ s.add_dependency(%q<rspec>, ["~> 1.3"])
59
+ end
60
+ else
61
+ s.add_dependency(%q<do_oracle>, ["~> 0.10.1"])
62
+ s.add_dependency(%q<dm-do-adapter>, ["~> 1.0.0.rc1"])
63
+ s.add_dependency(%q<rspec>, ["~> 1.3"])
64
+ end
65
+ end
66
+
@@ -0,0 +1 @@
1
+ require 'dm-oracle-adapter/adapter'
@@ -0,0 +1,228 @@
1
+ require 'do_oracle'
2
+ require 'dm-do-adapter'
3
+
4
+ module DataMapper
5
+
6
+ class Property
7
+ # for custom sequence names
8
+ OPTIONS << :sequence
9
+ end
10
+
11
+ module Adapters
12
+ class OracleAdapter < DataObjectsAdapter
13
+ module SQL #:nodoc:
14
+ IDENTIFIER_MAX_LENGTH = 30
15
+
16
+ private
17
+
18
+ # Constructs INSERT statement for given query,
19
+ #
20
+ # @return [String] INSERT statement as a string
21
+ #
22
+ # @api private
23
+ def insert_statement(model, properties, serial)
24
+ statement = "INSERT INTO #{quote_name(model.storage_name(name))} "
25
+
26
+ no_properties = properties.empty?
27
+ custom_sequence = serial && serial.options[:sequence]
28
+ serial_field = serial && quote_name(serial.field)
29
+
30
+ if supports_default_values? && no_properties && !custom_sequence
31
+ statement << "(#{serial_field}) " if serial
32
+ statement << default_values_clause
33
+ else
34
+ # do not use custom sequence if identity field was assigned a value
35
+ if custom_sequence && properties.include?(serial)
36
+ custom_sequence = nil
37
+ end
38
+ statement << "("
39
+ if custom_sequence
40
+ statement << "#{serial_field}"
41
+ statement << ", " unless no_properties
42
+ end
43
+ statement << "#{properties.map { |property| quote_name(property.field) }.join(', ')}) "
44
+ statement << "VALUES ("
45
+ if custom_sequence
46
+ statement << "#{quote_name(custom_sequence)}.NEXTVAL"
47
+ statement << ", " unless no_properties
48
+ end
49
+ statement << "#{(['?'] * properties.size).join(', ')})"
50
+ end
51
+
52
+ if supports_returning? && serial
53
+ statement << returning_clause(serial)
54
+ end
55
+
56
+ statement
57
+ end
58
+
59
+ # Oracle syntax for inserting default values
60
+ def default_values_clause
61
+ 'VALUES (DEFAULT)'
62
+ end
63
+
64
+ # @api private
65
+ def supports_returning?
66
+ true
67
+ end
68
+
69
+ # INTO :insert_id is recognized by Oracle DataObjects driver
70
+ def returning_clause(serial)
71
+ " RETURNING #{quote_name(serial.field)} INTO :insert_id"
72
+ end
73
+
74
+ # Constructs SELECT statement for given query,
75
+ # Overrides DataObjects adapter implementation with using subquery instead of GROUP BY to get unique records
76
+ #
77
+ # @return [String] SELECT statement as a string
78
+ #
79
+ # @api private
80
+ def select_statement(query)
81
+ name = self.name
82
+ model = query.model
83
+ fields = query.fields
84
+ conditions = query.conditions
85
+ limit = query.limit
86
+ offset = query.offset
87
+ order = query.order
88
+ group_by = nil
89
+
90
+ # FIXME: using a boolean for qualify does not work in some cases,
91
+ # such as when you have a self-referrential many to many association.
92
+ # if you don't qualfiy the columns with a unique alias, then the
93
+ # SQL query will fail. This may mean though, that it might not
94
+ # be enough to pass in a Property, but we may need to know the
95
+ # table and the alias we should use for the column.
96
+
97
+ qualify = query.links.any?
98
+
99
+ if query.unique?
100
+ group_by = fields.select { |property| property.kind_of?(Property) }
101
+ end
102
+
103
+ # create subquery to find all valid keys and then use these keys to retrive all other columns
104
+ use_subquery = qualify
105
+ no_group_by = group_by.blank?
106
+ no_order = order.blank?
107
+
108
+ # when we can include ROWNUM condition in main WHERE clause
109
+ use_simple_rownum_limit = limit && (offset||0 == 0) && no_group_by && no_order
110
+
111
+ unless (limit && limit > 1) || offset > 0 || qualify
112
+ # TODO: move this method to Query, so that it walks the conditions
113
+ # and finds an OR operator
114
+
115
+ # TODO: handle cases where two or more properties need to be
116
+ # used together to be unique
117
+
118
+ # if a unique property is used, and there is no OR operator, then an ORDER
119
+ # and LIMIT are unecessary because it should only return a single row
120
+ if conditions.respond_to?(:slug) && conditions.slug == :and &&
121
+ conditions.any? { |operand| operand.respond_to?(:slug) && operand.slug == :eql && operand.subject.respond_to?(:unique?) && operand.subject.unique? } &&
122
+ !conditions.any? { |operand| operand.respond_to?(:slug) && operand.slug == :or }
123
+ order = nil
124
+ no_order = true
125
+ limit = nil
126
+ end
127
+ end
128
+
129
+ conditions_statement, bind_values = conditions_statement(conditions, qualify)
130
+
131
+ model_key_column = columns_statement(model.key(name), qualify)
132
+ from_statement = " FROM #{quote_name(model.storage_name(name))}"
133
+
134
+ statement = "SELECT #{columns_statement(fields, qualify)}"
135
+ if use_subquery
136
+ statement << from_statement
137
+ statement << " WHERE (#{model_key_column}) IN"
138
+ statement << " (SELECT DISTINCT #{model_key_column}"
139
+ # do not need to do group by for uniqueness as just one row per primary key will be returned
140
+ no_group_by = true
141
+ end
142
+ statement << from_statement
143
+ statement << join_statement(query, bind_values, qualify) if qualify
144
+ statement << " WHERE (#{conditions_statement})" unless conditions_statement.blank?
145
+ if use_subquery
146
+ statement << ")"
147
+ end
148
+ if use_simple_rownum_limit
149
+ statement << " AND rownum <= ?"
150
+ bind_values << limit
151
+ end
152
+ statement << " GROUP BY #{columns_statement(group_by, qualify)}" unless no_group_by
153
+ statement << " ORDER BY #{order_statement(order, qualify)}" unless no_order
154
+
155
+ add_limit_offset!(statement, limit, offset, bind_values) unless use_simple_rownum_limit
156
+
157
+ return statement, bind_values
158
+ end
159
+
160
+ # Oracle does not support LIMIT and OFFSET
161
+ # Functionality is mimiced through the use of nested selects.
162
+ # See http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:127412348064
163
+ def add_limit_offset!(statement, limit, offset, bind_values)
164
+ positive_offset = offset > 0
165
+
166
+ if limit && positive_offset
167
+ statement.replace "select * from (select raw_sql_.*, rownum raw_rnum_ from (#{statement}) raw_sql_ where rownum <= ?) where raw_rnum_ > ?"
168
+ bind_values << offset + limit << offset
169
+ elsif limit
170
+ statement.replace "select raw_sql_.* from (#{statement}) raw_sql_ where rownum <= ?"
171
+ bind_values << limit
172
+ elsif positive_offset
173
+ statement.replace "select * from (select raw_sql_.*, rownum raw_rnum_ from (#{statement}) raw_sql_) where raw_rnum_ > ?"
174
+ bind_values << offset
175
+ end
176
+ end
177
+
178
+ # @api private
179
+ # Oracle does not allow " in table or column names therefore substitute them with underscore
180
+ def quote_name(name)
181
+ "\"#{oracle_upcase(name)[0, self.class::IDENTIFIER_MAX_LENGTH].gsub('"', '_')}\""
182
+ end
183
+
184
+ # If table or column name contains just lowercase characters then do uppercase
185
+ # as uppercase version will be used in Oracle data dictionary tables
186
+ def oracle_upcase(name)
187
+ name =~ /[A-Z]/ ? name : name.upcase
188
+ end
189
+
190
+ # CLOB value should be compared using DBMS_LOB.SUBSTR function
191
+ # NOTE: just first 32767 bytes will be compared!
192
+ # @api private
193
+ def equality_operator(property, operand)
194
+ if operand.nil?
195
+ 'IS'
196
+ elsif property.type == Types::Text
197
+ 'DBMS_LOB.SUBSTR(%s) = ?'
198
+ else
199
+ '='
200
+ end
201
+ end
202
+
203
+ # @api private
204
+ def include_operator(property, operand)
205
+ operator = case operand
206
+ when Array then 'IN'
207
+ when Range then 'BETWEEN'
208
+ end
209
+ if property.type == Types::Text
210
+ "DBMS_LOB.SUBSTR(%s) #{operator} ?"
211
+ else
212
+ operator
213
+ end
214
+ end
215
+
216
+ # @api private
217
+ def regexp_operator(operand)
218
+ 'REGEXP_LIKE(%s, ?)'
219
+ end
220
+
221
+ end #module SQL
222
+
223
+ include SQL
224
+ end # class OracleAdapter
225
+
226
+ const_added(:OracleAdapter)
227
+ end # module Adapters
228
+ end # module DataMapper
@@ -0,0 +1,18 @@
1
+ require 'dm-oracle-adapter'
2
+ require 'dm-core/spec/setup'
3
+
4
+ module DataMapper
5
+ module Spec
6
+ module Adapters
7
+
8
+ class OracleAdapter < Adapter
9
+ def test_connection
10
+ adapter.select('SELECT 1 FROM dual')
11
+ end
12
+ end
13
+
14
+ use OracleAdapter
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,208 @@
1
+ require 'spec_helper'
2
+
3
+ require 'dm-core/spec/shared/adapter_spec'
4
+ require 'dm-do-adapter/spec/shared_spec'
5
+
6
+ require 'dm-migrations'
7
+ require 'dm-oracle-adapter/spec/setup'
8
+
9
+ ENV['ADAPTER'] = 'oracle'
10
+ ENV['ADAPTER_SUPPORTS'] = 'all'
11
+
12
+ module SQLLogHelper
13
+ class SQLLogger
14
+ attr_accessor :buffer
15
+ def initialize
16
+ @buffer = ""
17
+ end
18
+
19
+ def level; 0; end
20
+
21
+ def debug(string)
22
+ @buffer << string << "\n"
23
+ # puts "#{string.gsub(/\n/m,"<br/>\n")}<br/>"
24
+ end
25
+ end
26
+
27
+ def start_sql_log!
28
+ return if @sql_log_on
29
+ @sql_log_on = true
30
+ @old_logger = DataObjects::Oracle.logger
31
+ DataObjects::Oracle.logger = SQLLogger.new
32
+ end
33
+
34
+ def stop_sql_log!
35
+ return unless @sql_log_on
36
+ @sql_log_on = nil
37
+ DataObjects::Oracle.logger = @old_logger
38
+ end
39
+
40
+ def clear_sql_log!
41
+ return unless @sql_log_on
42
+ DataObjects::Oracle.logger.buffer = ""
43
+ end
44
+
45
+ def sql_log_buffer
46
+ DataObjects::Oracle.logger.buffer
47
+ end
48
+ end
49
+
50
+
51
+ describe 'DataMapper::Adapters::OracleAdapter' do
52
+
53
+ before :all do
54
+ @adapter = DataMapper::Spec.adapter
55
+ @repository = DataMapper.repository(@adapter.name)
56
+
57
+ # speed up test execution
58
+ @adapter.class_eval do
59
+ auto_migrate_with :delete # table data will be deleted instead of dropping and creating table
60
+ auto_migrate_reset_sequences false # primary key sequences will not be reset
61
+ end
62
+
63
+ end
64
+
65
+ it_should_behave_like "An Adapter"
66
+ it_should_behave_like "A DataObjects Adapter"
67
+
68
+
69
+ describe "sequences" do
70
+
71
+ include SQLLogHelper
72
+
73
+ before(:all) do
74
+ @auto_migrate_with = DataMapper::Adapters::OracleAdapter.auto_migrate_with
75
+ DataMapper::Adapters::OracleAdapter.auto_migrate_with :drop_and_create
76
+ start_sql_log!
77
+ end
78
+
79
+ after(:all) do
80
+ stop_sql_log!
81
+ DataMapper::Adapters::OracleAdapter.auto_migrate_with @auto_migrate_with
82
+ end
83
+
84
+ describe "create default sequence and trigger" do
85
+ before(:all) do
86
+ class ::Employee
87
+ include DataMapper::Resource
88
+ property :employee_id, Serial
89
+ end
90
+ Employee.auto_migrate!
91
+ end
92
+
93
+ after(:all) do
94
+ Employee.auto_migrate_down!
95
+ end
96
+
97
+ it "should not have sequence name in options" do
98
+ Employee.properties[:employee_id].options[:sequence].should be_nil
99
+ end
100
+
101
+ it "should create default sequence" do
102
+ sql_log_buffer.should =~ /CREATE SEQUENCE "EMPLOYEES_SEQ"/
103
+ end
104
+
105
+ it "should create trigger" do
106
+ sql_log_buffer.should =~ /CREATE OR REPLACE TRIGGER "EMPLOYEES_PKT"/
107
+ end
108
+
109
+ end
110
+
111
+ describe "create custom sequence" do
112
+
113
+ before(:all) do
114
+ class ::Employee
115
+ include DataMapper::Resource
116
+ property :employee_id, Serial, :sequence => "emp_seq"
117
+ end
118
+ Employee.auto_migrate!
119
+ end
120
+
121
+ after(:all) do
122
+ Employee.auto_migrate_down!
123
+ end
124
+
125
+ it "should have custom sequence name" do
126
+ Employee.properties[:employee_id].options[:sequence].should == "emp_seq"
127
+ end
128
+
129
+ it "should create custom sequence" do
130
+ sql_log_buffer.should =~ /CREATE SEQUENCE "EMP_SEQ"/
131
+ end
132
+
133
+ it "should not create trigger" do
134
+ sql_log_buffer.should_not =~ /TRIGGER/
135
+ end
136
+
137
+ end
138
+
139
+ describe "create custom sequence in non-default repository" do
140
+
141
+ before(:all) do
142
+ stop_sql_log!
143
+ DataMapper.setup :oracle, DataMapper::Repository.adapters[:default].options
144
+ start_sql_log!
145
+ class ::Employee
146
+ include DataMapper::Resource
147
+ property :id, Serial
148
+ repository(:oracle) do
149
+ property :id, Serial, :field => "employee_id", :sequence => "emp_seq"
150
+ end
151
+ end
152
+ repository(:oracle) do
153
+ Employee.auto_migrate!
154
+ end
155
+ end
156
+
157
+ after(:all) do
158
+ repository(:oracle) do
159
+ Employee.auto_migrate_down!
160
+ end
161
+ end
162
+
163
+ it "should have custom sequence name" do
164
+ Employee.properties(:oracle)[:id].options[:sequence].should == "emp_seq"
165
+ end
166
+
167
+ it "should create custom sequence" do
168
+ sql_log_buffer.should =~ /CREATE SEQUENCE "EMP_SEQ"/
169
+ end
170
+
171
+ it "should not create trigger" do
172
+ sql_log_buffer.should_not =~ /TRIGGER/
173
+ end
174
+
175
+ end
176
+
177
+ describe "prefetch key value from custom sequence" do
178
+
179
+ before(:all) do
180
+ class ::Employee
181
+ include DataMapper::Resource
182
+ property :employee_id, Serial, :sequence => "emp_seq"
183
+ property :first_name, String
184
+ end
185
+ Employee.auto_migrate!
186
+ end
187
+
188
+ after(:all) do
189
+ Employee.auto_migrate_down!
190
+ end
191
+
192
+ it "should prefetch sequence value when inserting new record" do
193
+ e = Employee.create
194
+ e.employee_id.should == 1
195
+ e = Employee.create(:first_name => "Raimonds")
196
+ e.employee_id.should == 2
197
+ end
198
+
199
+ it "should insert explicitly specified primary key value" do
200
+ e = Employee.create(:employee_id => 100,:first_name => "Raimonds")
201
+ e.employee_id.should == 100
202
+ end
203
+
204
+ end
205
+
206
+
207
+ end
208
+ end
data/spec/rcov.opts ADDED
@@ -0,0 +1,5 @@
1
+ --exclude "spec"
2
+ --sort coverage
3
+ --callsites
4
+ --xrefs
5
+ --text-summary
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --loadby random
3
+ --backtrace
@@ -0,0 +1,5 @@
1
+ require 'dm-core/spec/lib/pending_helpers'
2
+
3
+ Spec::Runner.configure do |config|
4
+ config.include(DataMapper::Spec::PendingHelpers)
5
+ end
@@ -0,0 +1,18 @@
1
+ desc "Support bundling from local source code (allows BUNDLE_GEMFILE=Gemfile.local bundle foo)"
2
+ task :local_gemfile do |t|
3
+
4
+ root = Pathname(__FILE__).dirname.parent
5
+ datamapper = root.parent
6
+
7
+ source_regex = /DATAMAPPER = 'git:\/\/github.com\/datamapper'/
8
+ gem_source_regex = /:git => \"#\{DATAMAPPER\}\/(.+?)(?:\.git)?\"/
9
+
10
+ root.join('Gemfile.local').open('w') do |f|
11
+ root.join('Gemfile').open.each do |line|
12
+ line.sub!(source_regex, "DATAMAPPER = '#{datamapper}'")
13
+ line.sub!(gem_source_regex, ':path => "#{DATAMAPPER}/\1"')
14
+ f.puts line
15
+ end
16
+ end
17
+
18
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,38 @@
1
+ spec_defaults = lambda do |spec|
2
+ spec.pattern = 'spec/**/*_spec.rb'
3
+ spec.libs << 'lib' << 'spec'
4
+ spec.spec_opts << '--options' << 'spec/spec.opts'
5
+ end
6
+
7
+ begin
8
+ require 'spec/rake/spectask'
9
+
10
+ Spec::Rake::SpecTask.new(:spec, &spec_defaults)
11
+ rescue LoadError
12
+ task :spec do
13
+ abort 'rspec is not available. In order to run spec, you must: gem install rspec'
14
+ end
15
+ end
16
+
17
+ begin
18
+ require 'rcov'
19
+ require 'spec/rake/verify_rcov'
20
+
21
+ Spec::Rake::SpecTask.new(:rcov) do |rcov|
22
+ spec_defaults.call(rcov)
23
+ rcov.rcov = true
24
+ rcov.rcov_opts = File.read('spec/rcov.opts').split(/\s+/)
25
+ end
26
+
27
+ RCov::VerifyTask.new(:verify_rcov => :rcov) do |rcov|
28
+ rcov.threshold = 100
29
+ end
30
+ rescue LoadError
31
+ %w[ rcov verify_rcov ].each do |name|
32
+ task name do
33
+ abort "rcov is not available. In order to run #{name}, you must: gem install rcov"
34
+ end
35
+ end
36
+ end
37
+
38
+ task :default => :spec
data/tasks/yard.rake ADDED
@@ -0,0 +1,9 @@
1
+ begin
2
+ require 'yard'
3
+
4
+ YARD::Rake::YardocTask.new
5
+ rescue LoadError
6
+ task :yard do
7
+ abort 'YARD is not available. In order to run yard, you must: gem install yard'
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ begin
2
+ require 'pathname'
3
+ require 'yardstick/rake/measurement'
4
+ require 'yardstick/rake/verify'
5
+
6
+ # yardstick_measure task
7
+ Yardstick::Rake::Measurement.new
8
+
9
+ # verify_measurements task
10
+ Yardstick::Rake::Verify.new do |verify|
11
+ verify.threshold = 100
12
+ end
13
+ rescue LoadError
14
+ %w[ yardstick_measure verify_measurements ].each do |name|
15
+ task name.to_s do
16
+ abort "Yardstick is not available. In order to run #{name}, you must: gem install yardstick"
17
+ end
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dm-oracle-adapter
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: true
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ - rc1
10
+ version: 1.0.0.rc1
11
+ platform: ruby
12
+ authors:
13
+ - Dan Kubb
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-19 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: do_oracle
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 10
31
+ - 1
32
+ version: 0.10.1
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: dm-do-adapter
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 1
44
+ - 0
45
+ - 0
46
+ - rc1
47
+ version: 1.0.0.rc1
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rspec
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 1
59
+ - 3
60
+ version: "1.3"
61
+ type: :development
62
+ version_requirements: *id003
63
+ description: Oracle Adapter for DataMapper
64
+ email: dan.kubb@gmail.com
65
+ executables: []
66
+
67
+ extensions: []
68
+
69
+ extra_rdoc_files:
70
+ - LICENSE
71
+ files:
72
+ - .gitignore
73
+ - Gemfile
74
+ - LICENSE
75
+ - Rakefile
76
+ - VERSION
77
+ - dm-oracle-adapter.gemspec
78
+ - lib/dm-oracle-adapter.rb
79
+ - lib/dm-oracle-adapter/adapter.rb
80
+ - lib/dm-oracle-adapter/spec/setup.rb
81
+ - spec/adapter_spec.rb
82
+ - spec/rcov.opts
83
+ - spec/spec.opts
84
+ - spec/spec_helper.rb
85
+ - tasks/local_gemfile.rake
86
+ - tasks/spec.rake
87
+ - tasks/yard.rake
88
+ - tasks/yardstick.rake
89
+ has_rdoc: true
90
+ homepage: http://github.com/datamapper/dm-oracle-adapter
91
+ licenses: []
92
+
93
+ post_install_message:
94
+ rdoc_options:
95
+ - --charset=UTF-8
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">"
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 1
111
+ - 3
112
+ - 1
113
+ version: 1.3.1
114
+ requirements: []
115
+
116
+ rubyforge_project:
117
+ rubygems_version: 1.3.6
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: Oracle Adapter for DataMapper
121
+ test_files:
122
+ - spec/adapter_spec.rb
123
+ - spec/spec_helper.rb