ctreatma-activerecord-oracle_enhanced-adapter 1.4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.rspec +2 -0
  2. data/Gemfile +51 -0
  3. data/History.md +269 -0
  4. data/License.txt +20 -0
  5. data/README.md +378 -0
  6. data/RUNNING_TESTS.md +45 -0
  7. data/Rakefile +46 -0
  8. data/VERSION +1 -0
  9. data/activerecord-oracle_enhanced-adapter.gemspec +130 -0
  10. data/ctreatma-activerecord-oracle_enhanced-adapter.gemspec +129 -0
  11. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +5 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced.rake +105 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +41 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +1390 -0
  15. data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +106 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +136 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +119 -0
  18. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +328 -0
  19. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +25 -0
  20. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +21 -0
  21. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +39 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +553 -0
  23. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +492 -0
  24. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +260 -0
  25. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +213 -0
  26. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +252 -0
  27. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +373 -0
  28. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +265 -0
  29. data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +290 -0
  30. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +17 -0
  31. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +1 -0
  32. data/lib/activerecord-oracle_enhanced-adapter.rb +25 -0
  33. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +749 -0
  34. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +310 -0
  35. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +426 -0
  36. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +19 -0
  37. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +113 -0
  38. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +1330 -0
  39. data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +69 -0
  40. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +121 -0
  41. data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +25 -0
  42. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +374 -0
  43. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +380 -0
  44. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +1112 -0
  45. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +323 -0
  46. data/spec/spec_helper.rb +185 -0
  47. metadata +287 -0
@@ -0,0 +1,260 @@
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
+ if respond_to? :class_attribute
5
+ class_attribute :custom_create_method, :custom_update_method, :custom_delete_method
6
+ elsif respond_to? :class_inheritable_accessor
7
+ class_inheritable_accessor :custom_create_method, :custom_update_method, :custom_delete_method
8
+ end
9
+ end
10
+
11
+ require 'active_support'
12
+
13
+ module ActiveRecord #:nodoc:
14
+ module ConnectionAdapters #:nodoc:
15
+ module OracleEnhancedProcedures #:nodoc:
16
+
17
+ module ClassMethods
18
+ # Specify custom create method which should be used instead of Rails generated INSERT statement.
19
+ # Provided block should return ID of new record.
20
+ # Example:
21
+ # set_create_method do
22
+ # plsql.employees_pkg.create_employee(
23
+ # :p_first_name => first_name,
24
+ # :p_last_name => last_name,
25
+ # :p_employee_id => nil
26
+ # )[:p_employee_id]
27
+ # end
28
+ def set_create_method(&block)
29
+ include_with_custom_methods
30
+ self.custom_create_method = block
31
+ end
32
+
33
+ # Specify custom update method which should be used instead of Rails generated UPDATE statement.
34
+ # Example:
35
+ # set_update_method do
36
+ # plsql.employees_pkg.update_employee(
37
+ # :p_employee_id => id,
38
+ # :p_first_name => first_name,
39
+ # :p_last_name => last_name
40
+ # )
41
+ # end
42
+ def set_update_method(&block)
43
+ include_with_custom_methods
44
+ self.custom_update_method = block
45
+ end
46
+
47
+ # Specify custom delete method which should be used instead of Rails generated DELETE statement.
48
+ # Example:
49
+ # set_delete_method do
50
+ # plsql.employees_pkg.delete_employee(
51
+ # :p_employee_id => id
52
+ # )
53
+ # end
54
+ def set_delete_method(&block)
55
+ include_with_custom_methods
56
+ self.custom_delete_method = block
57
+ end
58
+
59
+ if ActiveRecord::VERSION::MAJOR < 3
60
+ def create_method_name_before_custom_methods #:nodoc:
61
+ if private_method_defined?(:create_without_timestamps) && defined?(ActiveRecord::VERSION) && ActiveRecord::VERSION::STRING.to_f >= 2.3
62
+ :create_without_timestamps
63
+ elsif private_method_defined?(:create_without_callbacks)
64
+ :create_without_callbacks
65
+ else
66
+ :create
67
+ end
68
+ end
69
+
70
+ def update_method_name_before_custom_methods #:nodoc:
71
+ if private_method_defined?(:update_without_dirty)
72
+ :update_without_dirty
73
+ elsif private_method_defined?(:update_without_timestamps) && defined?(ActiveRecord::VERSION) && ActiveRecord::VERSION::STRING.to_f >= 2.3
74
+ :update_without_timestamps
75
+ elsif private_method_defined?(:update_without_callbacks)
76
+ :update_without_callbacks
77
+ else
78
+ :update
79
+ end
80
+ end
81
+
82
+ def destroy_method_name_before_custom_methods #:nodoc:
83
+ if public_method_defined?(:destroy_without_callbacks)
84
+ :destroy_without_callbacks
85
+ else
86
+ :destroy
87
+ end
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ def include_with_custom_methods
94
+ unless included_modules.include? InstanceMethods
95
+ include InstanceMethods
96
+ end
97
+ end
98
+ end
99
+
100
+ module InstanceMethods #:nodoc:
101
+ def self.included(base)
102
+ # alias methods just for ActiveRecord 2.x
103
+ # for ActiveRecord 3.0 will just redefine create, update, delete methods which call super
104
+ if ActiveRecord::VERSION::MAJOR < 3
105
+ base.instance_eval do
106
+ alias_method :create_without_custom_method, create_method_name_before_custom_methods
107
+ alias_method create_method_name_before_custom_methods, :create_with_custom_method
108
+ alias_method :update_without_custom_method, update_method_name_before_custom_methods
109
+ alias_method update_method_name_before_custom_methods, :update_with_custom_method
110
+ alias_method :destroy_without_custom_method, destroy_method_name_before_custom_methods
111
+ alias_method destroy_method_name_before_custom_methods, :destroy_with_custom_method
112
+ private :create, :update
113
+ public :destroy
114
+ end
115
+ end
116
+ end
117
+
118
+ if ActiveRecord::VERSION::MAJOR >= 3
119
+ def destroy #:nodoc:
120
+ # check if class has custom delete method
121
+ if self.class.custom_delete_method
122
+ # wrap destroy in transaction
123
+ with_transaction_returning_status do
124
+ # run before/after callbacks defined in model
125
+ _run_destroy_callbacks { destroy_using_custom_method }
126
+ end
127
+ else
128
+ super
129
+ end
130
+ end
131
+ end
132
+
133
+ private
134
+
135
+ # Creates a record with custom create method
136
+ # and returns its id.
137
+ if ActiveRecord::VERSION::MAJOR < 3
138
+ def create_with_custom_method
139
+ # check if class has custom create method
140
+ self.class.custom_create_method ? create_using_custom_method : create_without_custom_method
141
+ end
142
+ else # ActiveRecord 3.x
143
+ def create
144
+ # check if class has custom create method
145
+ if self.class.custom_create_method
146
+ set_timestamps_before_custom_create_method
147
+ # run before/after callbacks defined in model
148
+ _run_create_callbacks { create_using_custom_method }
149
+ else
150
+ super
151
+ end
152
+ end
153
+ end
154
+
155
+ def create_using_custom_method
156
+ self.class.connection.log_custom_method("custom create method", "#{self.class.name} Create") do
157
+ self.id = instance_eval(&self.class.custom_create_method)
158
+ end
159
+ @new_record = false
160
+ # Starting from ActiveRecord 3.0.3 @persisted is used instead of @new_record
161
+ @persisted = true
162
+ id
163
+ end
164
+
165
+ # Updates the associated record with custom update method
166
+ # Returns the number of affected rows.
167
+ if ActiveRecord::VERSION::MAJOR < 3
168
+ def update_with_custom_method(attribute_names = @attributes.keys)
169
+ # check if class has custom create method
170
+ self.class.custom_update_method ? update_using_custom_method(attribute_names) : update_without_custom_method(attribute_names)
171
+ end
172
+ else # ActiveRecord 3.x
173
+ def update(attribute_names = @attributes.keys)
174
+ # check if class has custom update method
175
+ if self.class.custom_update_method
176
+ set_timestamps_before_custom_update_method
177
+ # run before/after callbacks defined in model
178
+ _run_update_callbacks do
179
+ # update just dirty attributes
180
+ if partial_updates?
181
+ # Serialized attributes should always be written in case they've been
182
+ # changed in place.
183
+ update_using_custom_method(changed | (attributes.keys & self.class.serialized_attributes.keys))
184
+ else
185
+ update_using_custom_method(attribute_names)
186
+ end
187
+ end
188
+ else
189
+ super
190
+ end
191
+ end
192
+ end
193
+
194
+ def update_using_custom_method(attribute_names)
195
+ return 0 if attribute_names.empty?
196
+ self.class.connection.log_custom_method("custom update method with #{self.class.primary_key}=#{self.id}", "#{self.class.name} Update") do
197
+ instance_eval(&self.class.custom_update_method)
198
+ end
199
+ 1
200
+ end
201
+
202
+ # Deletes the record in the database with custom delete method
203
+ # and freezes this instance to reflect that no changes should
204
+ # be made (since they can't be persisted).
205
+ if ActiveRecord::VERSION::MAJOR < 3
206
+ def destroy_with_custom_method
207
+ # check if class has custom delete method
208
+ self.class.custom_delete_method ? destroy_using_custom_method : destroy_without_custom_method
209
+ end
210
+ end
211
+
212
+ def destroy_using_custom_method
213
+ unless new_record? || @destroyed
214
+ self.class.connection.log_custom_method("custom delete method with #{self.class.primary_key}=#{self.id}", "#{self.class.name} Destroy") do
215
+ instance_eval(&self.class.custom_delete_method)
216
+ end
217
+ end
218
+
219
+ @destroyed = true
220
+ freeze
221
+ end
222
+
223
+ if ActiveRecord::VERSION::MAJOR >= 3
224
+ def set_timestamps_before_custom_create_method
225
+ if record_timestamps
226
+ current_time = current_time_from_proper_timezone
227
+
228
+ write_attribute('created_at', current_time) if respond_to?(:created_at) && created_at.nil?
229
+ write_attribute('created_on', current_time) if respond_to?(:created_on) && created_on.nil?
230
+
231
+ write_attribute('updated_at', current_time) if respond_to?(:updated_at) && updated_at.nil?
232
+ write_attribute('updated_on', current_time) if respond_to?(:updated_on) && updated_on.nil?
233
+ end
234
+ end
235
+
236
+ def set_timestamps_before_custom_update_method
237
+ if record_timestamps && (!partial_updates? || changed?)
238
+ current_time = current_time_from_proper_timezone
239
+
240
+ write_attribute('updated_at', current_time) if respond_to?(:updated_at)
241
+ write_attribute('updated_on', current_time) if respond_to?(:updated_on)
242
+ end
243
+ end
244
+ end
245
+
246
+ end
247
+
248
+ end
249
+ end
250
+ end
251
+
252
+ ActiveRecord::Base.class_eval do
253
+ extend ActiveRecord::ConnectionAdapters::OracleEnhancedProcedures::ClassMethods
254
+ end
255
+
256
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
257
+ # public alias to log method which could be used from other objects
258
+ alias_method :log_custom_method, :log
259
+ public :log_custom_method
260
+ end
@@ -0,0 +1,213 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class OracleEnhancedForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
4
+ end
5
+
6
+ class OracleEnhancedSynonymDefinition < Struct.new(:name, :table_owner, :table_name, :db_link) #:nodoc:
7
+ end
8
+
9
+ class OracleEnhancedIndexDefinition < Struct.new(:table, :name, :unique, :type, :parameters, :statement_parameters,
10
+ :tablespace, :columns) #:nodoc:
11
+ end
12
+
13
+ module OracleEnhancedColumnDefinition
14
+ def self.included(base) #:nodoc:
15
+ base.class_eval do
16
+ alias_method_chain :to_sql, :virtual_columns
17
+ alias to_s :to_sql
18
+ end
19
+ end
20
+
21
+ def to_sql_with_virtual_columns
22
+ if type==:virtual
23
+ column_sql = "#{base.quote_column_name(name)} AS (#{default})"
24
+ else
25
+ column_sql = to_sql_without_virtual_columns
26
+ if type==:primary_key
27
+ column_sql << base.table_definition_tablespace
28
+ end
29
+ end
30
+ column_sql
31
+ end
32
+
33
+ def lob?
34
+ ['CLOB', 'BLOB'].include?(sql_type)
35
+ end
36
+ end
37
+
38
+ module OracleEnhancedSchemaDefinitions #:nodoc:
39
+ def self.included(base)
40
+ base::TableDefinition.class_eval do
41
+ include OracleEnhancedTableDefinition
42
+ end
43
+
44
+ base::ColumnDefinition.class_eval do
45
+ include OracleEnhancedColumnDefinition
46
+ end
47
+
48
+ # Available starting from ActiveRecord 2.1
49
+ base::Table.class_eval do
50
+ include OracleEnhancedTable
51
+ end if defined?(base::Table)
52
+ end
53
+ end
54
+
55
+ module OracleEnhancedTableDefinition
56
+ class ForeignKey < Struct.new(:base, :to_table, :options) #:nodoc:
57
+ def to_sql
58
+ base.foreign_key_definition(to_table, options) << base.table_definition_tablespace
59
+ end
60
+ alias to_s :to_sql
61
+ end
62
+
63
+ def raw(name, options={})
64
+ column(name, :raw, options)
65
+ end
66
+
67
+ def self.included(base) #:nodoc:
68
+ base.class_eval do
69
+ alias_method_chain :references, :foreign_keys
70
+ alias_method_chain :to_sql, :foreign_keys
71
+
72
+ def virtual(* args)
73
+ options = args.extract_options!
74
+ column_names = args
75
+ column_names.each { |name| column(name, :virtual, options) }
76
+ end
77
+
78
+ end
79
+ end
80
+
81
+ # Adds a :foreign_key option to TableDefinition.references.
82
+ # If :foreign_key is true, a foreign key constraint is added to the table.
83
+ # You can also specify a hash, which is passed as foreign key options.
84
+ #
85
+ # ===== Examples
86
+ # ====== Add goat_id column and a foreign key to the goats table.
87
+ # t.references(:goat, :foreign_key => true)
88
+ # ====== Add goat_id column and a cascading foreign key to the goats table.
89
+ # t.references(:goat, :foreign_key => {:dependent => :delete})
90
+ #
91
+ # Note: No foreign key is created if :polymorphic => true is used.
92
+ # Note: If no name is specified, the database driver creates one for you!
93
+ def references_with_foreign_keys(*args)
94
+ options = args.extract_options!
95
+ fk_options = options.delete(:foreign_key)
96
+
97
+ if fk_options && !options[:polymorphic]
98
+ fk_options = {} if fk_options == true
99
+ args.each { |to_table| foreign_key(to_table, fk_options) }
100
+ end
101
+
102
+ references_without_foreign_keys(*(args << options))
103
+ end
104
+
105
+ # Defines a foreign key for the table. +to_table+ can be a single Symbol, or
106
+ # an Array of Symbols. See SchemaStatements#add_foreign_key
107
+ #
108
+ # ===== Examples
109
+ # ====== Creating a simple foreign key
110
+ # t.foreign_key(:people)
111
+ # ====== Defining the column
112
+ # t.foreign_key(:people, :column => :sender_id)
113
+ # ====== Creating a named foreign key
114
+ # t.foreign_key(:people, :column => :sender_id, :name => 'sender_foreign_key')
115
+ # ====== Defining the column of the +to_table+.
116
+ # t.foreign_key(:people, :column => :sender_id, :primary_key => :person_id)
117
+ def foreign_key(to_table, options = {})
118
+ if @base.respond_to?(:supports_foreign_keys?) && @base.supports_foreign_keys?
119
+ to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
120
+ foreign_keys << ForeignKey.new(@base, to_table, options)
121
+ else
122
+ raise ArgumentError, "this ActiveRecord adapter is not supporting foreign_key definition"
123
+ end
124
+ end
125
+
126
+ def to_sql_with_foreign_keys #:nodoc:
127
+ sql = to_sql_without_foreign_keys
128
+ sql << ', ' << (foreign_keys * ', ') unless foreign_keys.blank?
129
+ sql
130
+ end
131
+
132
+ def lob_columns
133
+ columns.select(&:lob?)
134
+ end
135
+
136
+ private
137
+ def foreign_keys
138
+ @foreign_keys ||= []
139
+ end
140
+ end
141
+
142
+ module OracleEnhancedTable
143
+ def self.included(base) #:nodoc:
144
+ base.class_eval do
145
+ alias_method_chain :references, :foreign_keys
146
+ end
147
+ end
148
+
149
+ # Adds a new foreign key to the table. +to_table+ can be a single Symbol, or
150
+ # an Array of Symbols. See SchemaStatements#add_foreign_key
151
+ #
152
+ # ===== Examples
153
+ # ====== Creating a simple foreign key
154
+ # t.foreign_key(:people)
155
+ # ====== Defining the column
156
+ # t.foreign_key(:people, :column => :sender_id)
157
+ # ====== Creating a named foreign key
158
+ # t.foreign_key(:people, :column => :sender_id, :name => 'sender_foreign_key')
159
+ # ====== Defining the column of the +to_table+.
160
+ # t.foreign_key(:people, :column => :sender_id, :primary_key => :person_id)
161
+ def foreign_key(to_table, options = {})
162
+ if @base.respond_to?(:supports_foreign_keys?) && @base.supports_foreign_keys?
163
+ to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
164
+ @base.add_foreign_key(@table_name, to_table, options)
165
+ else
166
+ raise ArgumentError, "this ActiveRecord adapter is not supporting foreign_key definition"
167
+ end
168
+ end
169
+
170
+ # Remove the given foreign key from the table.
171
+ #
172
+ # ===== Examples
173
+ # ====== Remove the suppliers_company_id_fk in the suppliers table.
174
+ # t.remove_foreign_key :companies
175
+ # ====== Remove the foreign key named accounts_branch_id_fk in the accounts table.
176
+ # remove_foreign_key :column => :branch_id
177
+ # ====== Remove the foreign key named party_foreign_key in the accounts table.
178
+ # remove_index :name => :party_foreign_key
179
+ def remove_foreign_key(options = {})
180
+ @base.remove_foreign_key(@table_name, options)
181
+ end
182
+
183
+ # Adds a :foreign_key option to TableDefinition.references.
184
+ # If :foreign_key is true, a foreign key constraint is added to the table.
185
+ # You can also specify a hash, which is passed as foreign key options.
186
+ #
187
+ # ===== Examples
188
+ # ====== Add goat_id column and a foreign key to the goats table.
189
+ # t.references(:goat, :foreign_key => true)
190
+ # ====== Add goat_id column and a cascading foreign key to the goats table.
191
+ # t.references(:goat, :foreign_key => {:dependent => :delete})
192
+ #
193
+ # Note: No foreign key is created if :polymorphic => true is used.
194
+ def references_with_foreign_keys(*args)
195
+ options = args.extract_options!
196
+ polymorphic = options[:polymorphic]
197
+ fk_options = options.delete(:foreign_key)
198
+
199
+ references_without_foreign_keys(*(args << options))
200
+ # references_without_foreign_keys adds {:type => :integer}
201
+ args.extract_options!
202
+ if fk_options && !polymorphic
203
+ fk_options = {} if fk_options == true
204
+ args.each { |to_table| foreign_key(to_table, fk_options) }
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ ActiveRecord::ConnectionAdapters.class_eval do
212
+ include ActiveRecord::ConnectionAdapters::OracleEnhancedSchemaDefinitions
213
+ end