rsim-activerecord-oracle_enhanced-adapter 1.1.9.90

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,21 @@
1
+ module ActiveRecord #:nodoc:
2
+ module ConnectionAdapters #:nodoc:
3
+ module OracleEnhancedCpk #:nodoc:
4
+
5
+ # This mightn't be in Core, but count(distinct x,y) doesn't work for me
6
+ # RSI: return that not supported if composite_primary_keys gem is required
7
+ def supports_count_distinct? #:nodoc:
8
+ @supports_count_distinct ||= ! defined?(CompositePrimaryKeys)
9
+ end
10
+
11
+ def concat(*columns)
12
+ "(#{columns.join('||')})"
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+
19
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
20
+ include ActiveRecord::ConnectionAdapters::OracleEnhancedCpk
21
+ end
@@ -0,0 +1,39 @@
1
+ module ActiveRecord #:nodoc:
2
+ module ConnectionAdapters #:nodoc:
3
+ module OracleEnhancedDirty #:nodoc:
4
+
5
+ module InstanceMethods
6
+ private
7
+
8
+ def field_changed?(attr, old, value)
9
+ if column = column_for_attribute(attr)
10
+ # RSI: added also :decimal type
11
+ if (column.type == :integer || column.type == :decimal) && column.null && (old.nil? || old == 0)
12
+ # For nullable integer columns, NULL gets stored in database for blank (i.e. '') values.
13
+ # Hence we don't record it as a change if the value changes from nil to ''.
14
+ # If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll
15
+ # be typecast back to 0 (''.to_i => 0)
16
+ value = nil if value.blank?
17
+ # RSI: Oracle stores empty string '' or empty text (CLOB) as NULL
18
+ # therefore need to convert empty string value to nil if old value is nil
19
+ elsif (column.type == :string || column.type == :text) && column.null && old.nil?
20
+ value = nil if value == ''
21
+ else
22
+ value = column.type_cast(value)
23
+ end
24
+ end
25
+
26
+ old != value
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+
35
+ if ActiveRecord::Base.instance_methods.include?('changed?')
36
+ ActiveRecord::Base.class_eval do
37
+ include ActiveRecord::ConnectionAdapters::OracleEnhancedDirty::InstanceMethods
38
+ end
39
+ end
@@ -0,0 +1,110 @@
1
+ # define accessors before requiring ruby-plsql as these accessors are used in clob writing callback and should be
2
+ # available also if ruby-plsql could not be loaded
3
+ ActiveRecord::Base.class_eval do
4
+ class_inheritable_accessor :custom_create_method, :custom_update_method, :custom_delete_method
5
+ end
6
+
7
+ require 'ruby_plsql'
8
+ require 'activesupport'
9
+
10
+ module ActiveRecord #:nodoc:
11
+ module ConnectionAdapters #:nodoc:
12
+ module OracleEnhancedProcedures #:nodoc:
13
+
14
+ module ClassMethods
15
+ def set_create_method(&block)
16
+ include_with_custom_methods
17
+ self.custom_create_method = block
18
+ end
19
+
20
+ def set_update_method(&block)
21
+ include_with_custom_methods
22
+ self.custom_update_method = block
23
+ end
24
+
25
+ def set_delete_method(&block)
26
+ include_with_custom_methods
27
+ self.custom_delete_method = block
28
+ end
29
+
30
+ private
31
+ def include_with_custom_methods
32
+ unless included_modules.include? InstanceMethods
33
+ include InstanceMethods
34
+ end
35
+ end
36
+ end
37
+
38
+ module InstanceMethods
39
+ def self.included(base)
40
+ base.instance_eval do
41
+ alias_method_chain :create, :custom_method
42
+ # insert after dirty checking in Rails 2.1
43
+ if private_instance_methods.include?('update_without_dirty')
44
+ alias_method :update_without_custom_method, :update_without_dirty
45
+ alias_method :update_without_dirty, :update_with_custom_method
46
+ else
47
+ alias_method_chain :update, :custom_method
48
+ end
49
+ private :create, :update
50
+ alias_method_chain :destroy, :custom_method
51
+ public :destroy
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ # Creates a record with custom create method
58
+ # and returns its id.
59
+ def create_with_custom_method
60
+ # check if class has custom create method
61
+ return create_without_custom_method unless self.class.custom_create_method
62
+ self.class.connection.log_custom_method("custom create method", "#{self.class.name} Create") do
63
+ self.id = self.class.custom_create_method.bind(self).call
64
+ end
65
+ @new_record = false
66
+ id
67
+ end
68
+
69
+ # Updates the associated record with custom update method
70
+ # Returns the number of affected rows.
71
+ def update_with_custom_method(attribute_names = @attributes.keys)
72
+ # check if class has custom create method
73
+ return update_without_custom_method unless self.class.custom_update_method
74
+ return 0 if attribute_names.empty?
75
+ self.class.connection.log_custom_method("custom update method with #{self.class.primary_key}=#{self.id}", "#{self.class.name} Update") do
76
+ self.class.custom_update_method.bind(self).call
77
+ end
78
+ 1
79
+ end
80
+
81
+ # Deletes the record in the database with custom delete method
82
+ # and freezes this instance to reflect that no changes should
83
+ # be made (since they can't be persisted).
84
+ def destroy_with_custom_method
85
+ # check if class has custom create method
86
+ return destroy_without_custom_method unless self.class.custom_delete_method
87
+ unless new_record?
88
+ self.class.connection.log_custom_method("custom delete method with #{self.class.primary_key}=#{self.id}", "#{self.class.name} Destroy") do
89
+ self.class.custom_delete_method.bind(self).call
90
+ end
91
+ end
92
+
93
+ freeze
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+ end
100
+ end
101
+
102
+ ActiveRecord::Base.class_eval do
103
+ extend ActiveRecord::ConnectionAdapters::OracleEnhancedProcedures::ClassMethods
104
+ end
105
+
106
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
107
+ # public alias to log method which could be used from other objects
108
+ alias_method :log_custom_method, :log
109
+ public :log_custom_method
110
+ end
@@ -0,0 +1,126 @@
1
+ module ActiveRecord #:nodoc:
2
+ module ConnectionAdapters #:nodoc:
3
+ module OracleEnhancedReservedWords #:nodoc:
4
+
5
+ RESERVED_WORDS = {
6
+ "ACCESS" => true,
7
+ "ADD" => true,
8
+ "ALL" => true,
9
+ "ALTER" => true,
10
+ "AND" => true,
11
+ "ANY" => true,
12
+ "AS" => true,
13
+ "ASC" => true,
14
+ "AUDIT" => true,
15
+ "BETWEEN" => true,
16
+ "BY" => true,
17
+ "CHAR" => true,
18
+ "CHECK" => true,
19
+ "CLUSTER" => true,
20
+ "COLUMN" => true,
21
+ "COMMENT" => true,
22
+ "COMPRESS" => true,
23
+ "CONNECT" => true,
24
+ "CREATE" => true,
25
+ "CURRENT" => true,
26
+ "DATE" => true,
27
+ "DECIMAL" => true,
28
+ "DEFAULT" => true,
29
+ "DELETE" => true,
30
+ "DESC" => true,
31
+ "DISTINCT" => true,
32
+ "DROP" => true,
33
+ "ELSE" => true,
34
+ "EXCLUSIVE" => true,
35
+ "EXISTS" => true,
36
+ "FILE" => true,
37
+ "FLOAT" => true,
38
+ "FOR" => true,
39
+ "FROM" => true,
40
+ "GRANT" => true,
41
+ "GROUP" => true,
42
+ "HAVING" => true,
43
+ "IDENTIFIED" => true,
44
+ "IMMEDIATE" => true,
45
+ "IN" => true,
46
+ "INCREMENT" => true,
47
+ "INDEX" => true,
48
+ "INITIAL" => true,
49
+ "INSERT" => true,
50
+ "INTEGER" => true,
51
+ "INTERSECT" => true,
52
+ "INTO" => true,
53
+ "IS" => true,
54
+ "LEVEL" => true,
55
+ "LIKE" => true,
56
+ "LOCK" => true,
57
+ "LONG" => true,
58
+ "MAXEXTENTS" => true,
59
+ "MINUS" => true,
60
+ "MLSLABEL" => true,
61
+ "MODE" => true,
62
+ "MODIFY" => true,
63
+ "NOAUDIT" => true,
64
+ "NOCOMPRESS" => true,
65
+ "NOT" => true,
66
+ "NOWAIT" => true,
67
+ "NULL" => true,
68
+ "NUMBER" => true,
69
+ "OF" => true,
70
+ "OFFLINE" => true,
71
+ "ON" => true,
72
+ "ONLINE" => true,
73
+ "OPTION" => true,
74
+ "OR" => true,
75
+ "ORDER" => true,
76
+ "PCTFREE" => true,
77
+ "PRIOR" => true,
78
+ "PRIVILEGES" => true,
79
+ "PUBLIC" => true,
80
+ "RAW" => true,
81
+ "RENAME" => true,
82
+ "RESOURCE" => true,
83
+ "REVOKE" => true,
84
+ "ROW" => true,
85
+ "ROWID" => true,
86
+ "ROWNUM" => true,
87
+ "ROWS" => true,
88
+ "SELECT" => true,
89
+ "SESSION" => true,
90
+ "SET" => true,
91
+ "SHARE" => true,
92
+ "SIZE" => true,
93
+ "SMALLINT" => true,
94
+ "START" => true,
95
+ "SUCCESSFUL" => true,
96
+ "SYNONYM" => true,
97
+ "SYSDATE" => true,
98
+ "TABLE" => true,
99
+ "THEN" => true,
100
+ "TO" => true,
101
+ "TRIGGER" => true,
102
+ "UID" => true,
103
+ "UNION" => true,
104
+ "UNIQUE" => true,
105
+ "UPDATE" => true,
106
+ "USER" => true,
107
+ "VALIDATE" => true,
108
+ "VALUES" => true,
109
+ "VARCHAR" => true,
110
+ "VARCHAR2" => true,
111
+ "VIEW" => true,
112
+ "WHENEVER" => true,
113
+ "WHERE" => true,
114
+ "WITH" => true
115
+ }
116
+
117
+ def quote_oracle_reserved_words(name)
118
+ RESERVED_WORDS[name.to_s.upcase].nil? ? name : "\"#{name}\""
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
125
+ include ActiveRecord::ConnectionAdapters::OracleEnhancedReservedWords
126
+ end
@@ -0,0 +1,11 @@
1
+ # RSI: implementation idea taken from JDBC adapter
2
+ if defined?(Rake.application) && Rake.application
3
+ oracle_enhanced_rakefile = File.dirname(__FILE__) + "/oracle_enhanced.rake"
4
+ if Rake.application.lookup("environment")
5
+ # rails tasks already defined; load the override tasks now
6
+ load oracle_enhanced_rakefile
7
+ else
8
+ # rails tasks not loaded yet; load as an import
9
+ Rake.application.add_import(oracle_enhanced_rakefile)
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module ActiveRecord #:nodoc:
2
+ module ConnectionAdapters #:nodoc:
3
+ module OracleEnhancedVersion #:nodoc:
4
+ MAJOR = 1
5
+ MINOR = 1
6
+ TINY = 9
7
+
8
+ STRING = [MAJOR, MINOR, TINY].join('.')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{activerecord-oracle_enhanced-adapter}
5
+ s.version = "1.1.9.90"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Raimonds Simanovskis"]
9
+ s.date = %q{2009-03-14}
10
+ s.description = %q{Oracle enhanced adapter for ActiveRecord}
11
+ s.email = ["raimonds.simanovskis@gmail.com"]
12
+ s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "README.txt"]
13
+ s.files = ["History.txt", "License.txt", "Manifest.txt", "README.txt",
14
+ "lib/active_record/connection_adapters/emulation/oracle_adapter.rb",
15
+ "lib/active_record/connection_adapters/oracle_enhanced.rake",
16
+ "lib/active_record/connection_adapters/oracle_enhanced_adapter.rb",
17
+ "lib/active_record/connection_adapters/oracle_enhanced_cpk.rb",
18
+ "lib/active_record/connection_adapters/oracle_enhanced_dirty.rb",
19
+ "lib/active_record/connection_adapters/oracle_enhanced_procedures.rb",
20
+ "lib/active_record/connection_adapters/oracle_enhanced_reserved_words.rb",
21
+ "lib/active_record/connection_adapters/oracle_enhanced_tasks.rb",
22
+ "lib/active_record/connection_adapters/oracle_enhanced_version.rb",
23
+ "oracle-enhanced.gemspec",
24
+ "spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb",
25
+ "spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb",
26
+ "spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb",
27
+ "spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb",
28
+ "spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb",
29
+ "spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb",
30
+ "spec/spec.opts",
31
+ "spec/spec_helper.rb"]
32
+ s.has_rdoc = true
33
+ s.homepage = %q{http://oracle-enhanced.rubyforge.org}
34
+ s.post_install_message = %q{}
35
+ s.rdoc_options = ["--main", "README.txt"]
36
+ s.require_paths = ["lib"]
37
+ s.rubyforge_project = %q{oracle-enhanced}
38
+ s.rubygems_version = %q{1.3.1}
39
+ s.summary = %q{Oracle enhanced adapter for ActiveRecord}
40
+
41
+ if s.respond_to? :specification_version then
42
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
+ s.specification_version = 2
44
+
45
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
46
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
47
+ else
48
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
49
+ end
50
+ else
51
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
52
+ end
53
+ end
@@ -0,0 +1,548 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe "OracleEnhancedAdapter establish connection" do
4
+
5
+ it "should connect to database" do
6
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
7
+ ActiveRecord::Base.connection.should_not be_nil
8
+ ActiveRecord::Base.connection.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
9
+ end
10
+
11
+ it "should connect to database as SYSDBA" do
12
+ ActiveRecord::Base.establish_connection(SYS_CONNECTION_PARAMS)
13
+ ActiveRecord::Base.connection.should_not be_nil
14
+ ActiveRecord::Base.connection.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
15
+ end
16
+
17
+ it "should be active after connection to database" do
18
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
19
+ ActiveRecord::Base.connection.should be_active
20
+ end
21
+
22
+ it "should not be active after disconnection to database" do
23
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
24
+ ActiveRecord::Base.connection.disconnect!
25
+ ActiveRecord::Base.connection.should_not be_active
26
+ end
27
+
28
+ it "should be active after reconnection to database" do
29
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
30
+ ActiveRecord::Base.connection.reconnect!
31
+ ActiveRecord::Base.connection.should be_active
32
+ end
33
+
34
+ end
35
+
36
+ describe "OracleEnhancedAdapter schema dump" do
37
+
38
+ before(:all) do
39
+ if !defined?(RUBY_ENGINE)
40
+ @old_conn = ActiveRecord::Base.oracle_connection(CONNECTION_PARAMS)
41
+ @old_conn.class.should == ActiveRecord::ConnectionAdapters::OracleAdapter
42
+ elsif RUBY_ENGINE == 'jruby'
43
+ @old_conn = ActiveRecord::Base.jdbc_connection(JDBC_CONNECTION_PARAMS)
44
+ @old_conn.class.should == ActiveRecord::ConnectionAdapters::JdbcAdapter
45
+ end
46
+
47
+ @new_conn = ActiveRecord::Base.oracle_enhanced_connection(CONNECTION_PARAMS)
48
+ @new_conn.class.should == ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
49
+ end
50
+
51
+ unless defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION =~ /^1\.9/
52
+ it "should return the same tables list as original oracle adapter" do
53
+ @new_conn.tables.sort.should == @old_conn.tables.sort
54
+ end
55
+
56
+ it "should return the same index list as original oracle adapter" do
57
+ @new_conn.indexes('employees').sort_by(&:name).should == @old_conn.indexes('employees').sort_by(&:name)
58
+ end
59
+
60
+ it "should return the same pk_and_sequence_for as original oracle adapter" do
61
+ if @old_conn.respond_to?(:pk_and_sequence_for)
62
+ @new_conn.tables.each do |t|
63
+ @new_conn.pk_and_sequence_for(t).should == @old_conn.pk_and_sequence_for(t)
64
+ end
65
+ end
66
+ end
67
+
68
+ it "should return the same structure dump as original oracle adapter" do
69
+ @new_conn.structure_dump.should == @old_conn.structure_dump
70
+ end
71
+
72
+ it "should return the same structure drop as original oracle adapter" do
73
+ @new_conn.structure_drop.should == @old_conn.structure_drop
74
+ end
75
+ end
76
+
77
+ it "should return the character size of nvarchar fields" do
78
+ @new_conn.execute <<-SQL
79
+ CREATE TABLE nvarchartable (
80
+ session_id NVARCHAR2(255) DEFAULT NULL
81
+ )
82
+ SQL
83
+ if /.*session_id nvarchar2\((\d+)\).*/ =~ @new_conn.structure_dump
84
+ "#$1".should == "255"
85
+ end
86
+ @new_conn.execute "DROP TABLE nvarchartable"
87
+ end
88
+ end
89
+
90
+ describe "OracleEnhancedAdapter database stucture dump extentions" do
91
+ before(:all) do
92
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
93
+ @conn = ActiveRecord::Base.connection
94
+ @conn.execute <<-SQL
95
+ CREATE TABLE nvarchartable (
96
+ unq_nvarchar NVARCHAR2(255) DEFAULT NULL
97
+ )
98
+ SQL
99
+ end
100
+
101
+ after(:all) do
102
+ @conn.execute "DROP TABLE nvarchartable"
103
+ end
104
+
105
+ it "should return the character size of nvarchar fields" do
106
+ if /.*unq_nvarchar nvarchar2\((\d+)\).*/ =~ @conn.structure_dump
107
+ "#$1".should == "255"
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "OracleEnhancedAdapter database session store" do
113
+ before(:all) do
114
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
115
+ @conn = ActiveRecord::Base.connection
116
+ @conn.execute <<-SQL
117
+ CREATE TABLE sessions (
118
+ id NUMBER(38,0) NOT NULL,
119
+ session_id VARCHAR2(255) DEFAULT NULL,
120
+ data CLOB DEFAULT NULL,
121
+ created_at DATE DEFAULT NULL,
122
+ updated_at DATE DEFAULT NULL,
123
+ PRIMARY KEY (ID)
124
+ )
125
+ SQL
126
+ @conn.execute <<-SQL
127
+ CREATE SEQUENCE sessions_seq MINVALUE 1 MAXVALUE 999999999999999999999999999
128
+ INCREMENT BY 1 START WITH 10040 CACHE 20 NOORDER NOCYCLE
129
+ SQL
130
+ end
131
+
132
+ after(:all) do
133
+ @conn.execute "DROP TABLE sessions"
134
+ @conn.execute "DROP SEQUENCE sessions_seq"
135
+ end
136
+
137
+ it "should create sessions table" do
138
+ ActiveRecord::Base.connection.tables.grep("sessions").should_not be_empty
139
+ end
140
+
141
+ it "should save session data" do
142
+ @session = CGI::Session::ActiveRecordStore::Session.new :session_id => "111111", :data => "something" #, :updated_at => Time.now
143
+ @session.save!
144
+ @session = CGI::Session::ActiveRecordStore::Session.find_by_session_id("111111")
145
+ @session.data.should == "something"
146
+ end
147
+
148
+ it "should change session data when partial updates enabled" do
149
+ return pending("Not in this ActiveRecord version") unless CGI::Session::ActiveRecordStore::Session.respond_to?(:partial_updates=)
150
+ CGI::Session::ActiveRecordStore::Session.partial_updates = true
151
+ @session = CGI::Session::ActiveRecordStore::Session.new :session_id => "222222", :data => "something" #, :updated_at => Time.now
152
+ @session.save!
153
+ @session = CGI::Session::ActiveRecordStore::Session.find_by_session_id("222222")
154
+ @session.data = "other thing"
155
+ @session.save!
156
+ # second save should call again blob writing callback
157
+ @session.save!
158
+ @session = CGI::Session::ActiveRecordStore::Session.find_by_session_id("222222")
159
+ @session.data.should == "other thing"
160
+ end
161
+
162
+ it "should have one enhanced_write_lobs callback" do
163
+ return pending("Not in this ActiveRecord version") unless CGI::Session::ActiveRecordStore::Session.respond_to?(:after_save_callback_chain)
164
+ CGI::Session::ActiveRecordStore::Session.after_save_callback_chain.select{|cb| cb.method == :enhanced_write_lobs}.should have(1).record
165
+ end
166
+
167
+ it "should not set sessions table session_id column type as integer if emulate_integers_by_column_name is true" do
168
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
169
+ columns = @conn.columns('sessions')
170
+ column = columns.detect{|c| c.name == "session_id"}
171
+ column.type.should == :string
172
+ end
173
+
174
+ end
175
+
176
+ describe "OracleEnhancedAdapter ignore specified table columns" do
177
+ before(:all) do
178
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
179
+ @conn = ActiveRecord::Base.connection
180
+ @conn.execute <<-SQL
181
+ CREATE TABLE test_employees (
182
+ id NUMBER,
183
+ first_name VARCHAR2(20),
184
+ last_name VARCHAR2(25),
185
+ email VARCHAR2(25),
186
+ phone_number VARCHAR2(20),
187
+ hire_date DATE,
188
+ job_id NUMBER,
189
+ salary NUMBER,
190
+ commission_pct NUMBER(2,2),
191
+ manager_id NUMBER(6),
192
+ department_id NUMBER(4,0),
193
+ created_at DATE
194
+ )
195
+ SQL
196
+ @conn.execute <<-SQL
197
+ CREATE SEQUENCE test_employees_seq MINVALUE 1
198
+ INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE
199
+ SQL
200
+ end
201
+
202
+ after(:all) do
203
+ @conn.execute "DROP TABLE test_employees"
204
+ @conn.execute "DROP SEQUENCE test_employees_seq"
205
+ end
206
+
207
+ after(:each) do
208
+ Object.send(:remove_const, "TestEmployee")
209
+ end
210
+
211
+ it "should ignore specified table columns" do
212
+ class TestEmployee < ActiveRecord::Base
213
+ ignore_table_columns :phone_number, :hire_date
214
+ end
215
+ TestEmployee.connection.columns('test_employees').select{|c| ['phone_number','hire_date'].include?(c.name) }.should be_empty
216
+ end
217
+
218
+ it "should ignore specified table columns specified in several lines" do
219
+ class TestEmployee < ActiveRecord::Base
220
+ ignore_table_columns :phone_number
221
+ ignore_table_columns :hire_date
222
+ end
223
+ TestEmployee.connection.columns('test_employees').select{|c| ['phone_number','hire_date'].include?(c.name) }.should be_empty
224
+ end
225
+
226
+ it "should not ignore unspecified table columns" do
227
+ class TestEmployee < ActiveRecord::Base
228
+ ignore_table_columns :phone_number, :hire_date
229
+ end
230
+ TestEmployee.connection.columns('test_employees').select{|c| c.name == 'email' }.should_not be_empty
231
+ end
232
+
233
+
234
+ end
235
+
236
+ describe "OracleEnhancedAdapter table and sequence creation with non-default primary key" do
237
+
238
+ before(:all) do
239
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
240
+ ActiveRecord::Schema.define do
241
+ suppress_messages do
242
+ create_table :keyboards, :force => true, :id => false do |t|
243
+ t.primary_key :key_number
244
+ t.string :name
245
+ end
246
+ create_table :id_keyboards, :force => true do |t|
247
+ t.string :name
248
+ end
249
+ end
250
+ end
251
+ class Keyboard < ActiveRecord::Base
252
+ set_primary_key :key_number
253
+ end
254
+ class IdKeyboard < ActiveRecord::Base
255
+ end
256
+ end
257
+
258
+ after(:all) do
259
+ ActiveRecord::Schema.define do
260
+ suppress_messages do
261
+ drop_table :keyboards
262
+ drop_table :id_keyboards
263
+ end
264
+ end
265
+ Object.send(:remove_const, "Keyboard")
266
+ Object.send(:remove_const, "IdKeyboard")
267
+ end
268
+
269
+ it "should create sequence for non-default primary key" do
270
+ ActiveRecord::Base.connection.next_sequence_value(Keyboard.sequence_name).should_not be_nil
271
+ end
272
+
273
+ it "should create sequence for default primary key" do
274
+ ActiveRecord::Base.connection.next_sequence_value(IdKeyboard.sequence_name).should_not be_nil
275
+ end
276
+ end
277
+
278
+ describe "OracleEnhancedAdapter without composite_primary_keys" do
279
+
280
+ before(:all) do
281
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
282
+ Object.send(:remove_const, 'CompositePrimaryKeys') if defined?(CompositePrimaryKeys)
283
+ class Employee < ActiveRecord::Base
284
+ set_primary_key :employee_id
285
+ end
286
+ end
287
+
288
+ it "should tell ActiveRecord that count distinct is supported" do
289
+ ActiveRecord::Base.connection.supports_count_distinct?.should be_true
290
+ end
291
+
292
+ it "should execute correct SQL COUNT DISTINCT statement" do
293
+ lambda { Employee.count(:employee_id, :distinct => true) }.should_not raise_error
294
+ end
295
+
296
+ end
297
+
298
+ describe "OracleEnhancedAdapter sequence creation parameters" do
299
+
300
+ before(:all) do
301
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
302
+ end
303
+
304
+ def create_test_employees_table(sequence_start_value = nil)
305
+ ActiveRecord::Schema.define do
306
+ suppress_messages do
307
+ create_table :test_employees, sequence_start_value ? {:sequence_start_value => sequence_start_value} : {} do |t|
308
+ t.string :first_name
309
+ t.string :last_name
310
+ end
311
+ end
312
+ end
313
+ end
314
+
315
+ def save_default_sequence_start_value
316
+ @saved_sequence_start_value = ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value
317
+ end
318
+
319
+ def restore_default_sequence_start_value
320
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = @saved_sequence_start_value
321
+ end
322
+
323
+ before(:each) do
324
+ save_default_sequence_start_value
325
+ end
326
+ after(:each) do
327
+ restore_default_sequence_start_value
328
+ ActiveRecord::Schema.define do
329
+ suppress_messages do
330
+ drop_table :test_employees
331
+ end
332
+ end
333
+ Object.send(:remove_const, "TestEmployee")
334
+ end
335
+
336
+ it "should use default sequence start value 10000" do
337
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value.should == 10000
338
+
339
+ create_test_employees_table
340
+ class TestEmployee < ActiveRecord::Base; end
341
+
342
+ employee = TestEmployee.create!
343
+ employee.id.should == 10000
344
+ end
345
+
346
+ it "should use specified default sequence start value" do
347
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = 1
348
+
349
+ create_test_employees_table
350
+ class TestEmployee < ActiveRecord::Base; end
351
+
352
+ employee = TestEmployee.create!
353
+ employee.id.should == 1
354
+ end
355
+
356
+ it "should use sequence start value from table definition" do
357
+ create_test_employees_table(10)
358
+ class TestEmployee < ActiveRecord::Base; end
359
+
360
+ employee = TestEmployee.create!
361
+ employee.id.should == 10
362
+ end
363
+
364
+ it "should use sequence start value and other options from table definition" do
365
+ create_test_employees_table("100 NOCACHE INCREMENT BY 10")
366
+ class TestEmployee < ActiveRecord::Base; end
367
+
368
+ employee = TestEmployee.create!
369
+ employee.id.should == 100
370
+ employee = TestEmployee.create!
371
+ employee.id.should == 110
372
+ end
373
+
374
+ end
375
+
376
+ describe "OracleEnhancedAdapter table and column comments" do
377
+
378
+ before(:all) do
379
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
380
+ @conn = ActiveRecord::Base.connection
381
+ end
382
+
383
+ def create_test_employees_table(table_comment=nil, column_comments={})
384
+ ActiveRecord::Schema.define do
385
+ suppress_messages do
386
+ create_table :test_employees, :comment => table_comment do |t|
387
+ t.string :first_name, :comment => column_comments[:first_name]
388
+ t.string :last_name, :comment => column_comments[:last_name]
389
+ end
390
+ end
391
+ end
392
+ end
393
+
394
+ after(:each) do
395
+ ActiveRecord::Schema.define do
396
+ suppress_messages do
397
+ drop_table :test_employees
398
+ end
399
+ end
400
+ Object.send(:remove_const, "TestEmployee")
401
+ ActiveRecord::Base.table_name_prefix = nil
402
+ end
403
+
404
+ it "should create table with table comment" do
405
+ table_comment = "Test Employees"
406
+ create_test_employees_table(table_comment)
407
+ class TestEmployee < ActiveRecord::Base; end
408
+
409
+ @conn.table_comment("test_employees").should == table_comment
410
+ TestEmployee.table_comment.should == table_comment
411
+ end
412
+
413
+ it "should create table with columns comment" do
414
+ column_comments = {:first_name => "Given Name", :last_name => "Surname"}
415
+ create_test_employees_table(nil, column_comments)
416
+ class TestEmployee < ActiveRecord::Base; end
417
+
418
+ [:first_name, :last_name].each do |attr|
419
+ @conn.column_comment("test_employees", attr.to_s).should == column_comments[attr]
420
+ end
421
+ [:first_name, :last_name].each do |attr|
422
+ TestEmployee.columns_hash[attr.to_s].comment.should == column_comments[attr]
423
+ end
424
+ end
425
+
426
+ it "should create table with table and columns comment and custom table name prefix" do
427
+ ActiveRecord::Base.table_name_prefix = "xxx_"
428
+ table_comment = "Test Employees"
429
+ column_comments = {:first_name => "Given Name", :last_name => "Surname"}
430
+ create_test_employees_table(table_comment, column_comments)
431
+ class TestEmployee < ActiveRecord::Base; end
432
+
433
+ @conn.table_comment(TestEmployee.table_name).should == table_comment
434
+ TestEmployee.table_comment.should == table_comment
435
+ [:first_name, :last_name].each do |attr|
436
+ @conn.column_comment(TestEmployee.table_name, attr.to_s).should == column_comments[attr]
437
+ end
438
+ [:first_name, :last_name].each do |attr|
439
+ TestEmployee.columns_hash[attr.to_s].comment.should == column_comments[attr]
440
+ end
441
+ end
442
+
443
+ end
444
+
445
+ describe "OracleEnhancedAdapter column quoting" do
446
+
447
+ before(:all) do
448
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
449
+ @conn = ActiveRecord::Base.connection
450
+ end
451
+
452
+ def create_test_reserved_words_table
453
+ ActiveRecord::Schema.define do
454
+ suppress_messages do
455
+ create_table :test_reserved_words do |t|
456
+ t.string :varchar2
457
+ t.integer :integer
458
+ end
459
+ end
460
+ end
461
+ end
462
+
463
+ after(:each) do
464
+ ActiveRecord::Schema.define do
465
+ suppress_messages do
466
+ drop_table :test_reserved_words
467
+ end
468
+ end
469
+ Object.send(:remove_const, "TestReservedWord")
470
+ ActiveRecord::Base.table_name_prefix = nil
471
+ end
472
+
473
+ it "should allow creation of a table with oracle reserved words as column names" do
474
+ create_test_reserved_words_table
475
+ class TestReservedWord < ActiveRecord::Base; end
476
+
477
+ [:varchar2, :integer].each do |attr|
478
+ TestReservedWord.columns_hash[attr.to_s].name.should == attr.to_s
479
+ end
480
+ end
481
+
482
+ end
483
+
484
+ describe "OracleEnhancedAdapter valid table names" do
485
+ before(:all) do
486
+ @adapter = ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
487
+ end
488
+ it "should be valid with letters and digits" do
489
+ @adapter.valid_table_name?("abc_123").should be_true
490
+ end
491
+
492
+ it "should be valid with schema name" do
493
+ @adapter.valid_table_name?("abc_123.def_456").should be_true
494
+ end
495
+
496
+ it "should be valid with $ in name" do
497
+ @adapter.valid_table_name?("sys.v$session").should be_true
498
+ end
499
+
500
+ it "should not be valid with two dots in name" do
501
+ @adapter.valid_table_name?("abc_123.def_456.ghi_789").should be_false
502
+ end
503
+
504
+ it "should not be valid with invalid characters" do
505
+ @adapter.valid_table_name?("warehouse-things").should be_false
506
+ end
507
+
508
+ end
509
+
510
+ describe "OracleEnhancedAdapter table quoting" do
511
+
512
+ before(:all) do
513
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
514
+ @conn = ActiveRecord::Base.connection
515
+ end
516
+
517
+ def create_warehouse_things_table
518
+ ActiveRecord::Schema.define do
519
+ suppress_messages do
520
+ create_table "warehouse-things" do |t|
521
+ t.string :name
522
+ t.integer :foo
523
+ end
524
+ end
525
+ end
526
+ end
527
+
528
+ after(:each) do
529
+ ActiveRecord::Schema.define do
530
+ suppress_messages do
531
+ drop_table "warehouse-things"
532
+ end
533
+ end
534
+ Object.send(:remove_const, "WarehouseThing")
535
+ ActiveRecord::Base.table_name_prefix = nil
536
+ end
537
+
538
+ it "should allow creation of a table with non alphanumeric characters" do
539
+ create_warehouse_things_table
540
+ class WarehouseThing < ActiveRecord::Base
541
+ set_table_name "warehouse-things"
542
+ end
543
+
544
+ wh = WarehouseThing.create!(:name => "Foo", :foo => 2)
545
+ wh.id.should_not be_nil
546
+ end
547
+
548
+ end