activerecord-oracle_enhanced-adapter 1.5.6 → 1.6.0

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/History.md +107 -0
  4. data/README.md +271 -174
  5. data/VERSION +1 -1
  6. data/activerecord-oracle_enhanced-adapter.gemspec +26 -22
  7. data/lib/active_record/connection_adapters/{oracle_enhanced_column.rb → oracle_enhanced/column.rb} +14 -63
  8. data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +65 -0
  9. data/lib/active_record/connection_adapters/{oracle_enhanced_connection.rb → oracle_enhanced/connection.rb} +2 -2
  10. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +347 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +257 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced/dirty.rb +40 -0
  13. data/lib/active_record/connection_adapters/{oracle_enhanced_schema_creation.rb → oracle_enhanced/schema_creation.rb} +17 -16
  14. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +95 -0
  15. data/lib/active_record/connection_adapters/{oracle_enhanced_schema_dumper.rb → oracle_enhanced/schema_dumper.rb} +4 -32
  16. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +546 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +65 -0
  18. data/lib/active_record/connection_adapters/{oracle_enhanced_structure_dump.rb → oracle_enhanced/structure_dump.rb} +26 -4
  19. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -0
  20. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +159 -66
  21. data/lib/active_record/oracle_enhanced/type/integer.rb +13 -0
  22. data/lib/active_record/oracle_enhanced/type/raw.rb +13 -0
  23. data/lib/active_record/oracle_enhanced/type/timestamp.rb +11 -0
  24. data/lib/activerecord-oracle_enhanced-adapter.rb +1 -1
  25. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +6 -31
  26. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +1 -1
  27. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +2 -2
  28. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +2 -2
  29. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +63 -63
  30. data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +1 -1
  31. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +7 -13
  32. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +25 -178
  33. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +14 -5
  34. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +1 -0
  35. data/spec/spec_config.yaml.template +10 -0
  36. data/spec/spec_helper.rb +21 -10
  37. metadata +27 -23
  38. data/lib/active_record/connection_adapters/oracle_enhanced_column_dumper.rb +0 -77
  39. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +0 -350
  40. data/lib/active_record/connection_adapters/oracle_enhanced_database_statements.rb +0 -262
  41. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +0 -45
  42. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +0 -197
  43. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +0 -450
  44. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +0 -258
  45. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +0 -1
  46. /data/lib/active_record/connection_adapters/{oracle_enhanced_cpk.rb → oracle_enhanced/cpk.rb} +0 -0
  47. /data/lib/active_record/connection_adapters/{oracle_enhanced_database_tasks.rb → oracle_enhanced/database_tasks.rb} +0 -0
  48. /data/lib/active_record/connection_adapters/{oracle_enhanced_jdbc_connection.rb → oracle_enhanced/jdbc_connection.rb} +0 -0
  49. /data/lib/active_record/connection_adapters/{oracle_enhanced_oci_connection.rb → oracle_enhanced/oci_connection.rb} +0 -0
  50. /data/lib/active_record/connection_adapters/{oracle_enhanced_procedures.rb → oracle_enhanced/procedures.rb} +0 -0
@@ -1,262 +0,0 @@
1
- module ActiveRecord
2
- module ConnectionAdapters
3
- module OracleEnhancedDatabaseStatements
4
- # DATABASE STATEMENTS ======================================
5
- #
6
- # see: abstract/database_statements.rb
7
-
8
- # Executes a SQL statement
9
- def execute(sql, name = nil)
10
- log(sql, name) { @connection.exec(sql) }
11
- end
12
-
13
- def substitute_at(column, index)
14
- Arel::Nodes::BindParam.new (":a#{index + 1}")
15
- end
16
-
17
- def clear_cache!
18
- @statements.clear
19
- end
20
-
21
- def exec_query(sql, name = 'SQL', binds = [])
22
- type_casted_binds = binds.map { |col, val|
23
- [col, type_cast(val, col)]
24
- }
25
- log(sql, name, type_casted_binds) do
26
- cursor = nil
27
- cached = false
28
- if without_prepared_statement?(binds)
29
- cursor = @connection.prepare(sql)
30
- else
31
- unless @statements.key? sql
32
- @statements[sql] = @connection.prepare(sql)
33
- end
34
-
35
- cursor = @statements[sql]
36
-
37
- binds.each_with_index do |bind, i|
38
- col, val = bind
39
- cursor.bind_param(i + 1, type_cast(val, col), col)
40
- end
41
-
42
- cached = true
43
- end
44
-
45
- cursor.exec
46
-
47
- if name == 'EXPLAIN' and sql =~ /^EXPLAIN/
48
- res = true
49
- else
50
- columns = cursor.get_col_names.map do |col_name|
51
- @connection.oracle_downcase(col_name)
52
- end
53
- rows = []
54
- fetch_options = {:get_lob_value => (name != 'Writable Large Object')}
55
- while row = cursor.fetch(fetch_options)
56
- rows << row
57
- end
58
- res = ActiveRecord::Result.new(columns, rows)
59
- end
60
-
61
- cursor.close unless cached
62
- res
63
- end
64
- end
65
-
66
- def supports_statement_cache?
67
- true
68
- end
69
-
70
- def supports_explain?
71
- true
72
- end
73
-
74
- def explain(arel, binds = [])
75
- sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
76
- return if sql =~ /FROM all_/
77
- if ORACLE_ENHANCED_CONNECTION == :jdbc
78
- exec_query(sql, 'EXPLAIN', binds)
79
- else
80
- exec_query(sql, 'EXPLAIN')
81
- end
82
- select_values("SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)", 'EXPLAIN').join("\n")
83
- end
84
-
85
- # Returns an array of arrays containing the field values.
86
- # Order is the same as that returned by #columns.
87
- def select_rows(sql, name = nil, binds = [])
88
- exec_query(sql, name, binds).rows
89
- end
90
-
91
- # Executes an INSERT statement and returns the new record's ID
92
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
93
- # if primary key value is already prefetched from sequence
94
- # or if there is no primary key
95
- if id_value || pk.nil?
96
- execute(sql, name)
97
- return id_value
98
- end
99
-
100
- sql_with_returning = sql + @connection.returning_clause(quote_column_name(pk))
101
- log(sql, name) do
102
- @connection.exec_with_returning(sql_with_returning)
103
- end
104
- end
105
- protected :insert_sql
106
-
107
- # New method in ActiveRecord 3.1
108
- # Will add RETURNING clause in case of trigger generated primary keys
109
- def sql_for_insert(sql, pk, id_value, sequence_name, binds)
110
- unless id_value || pk.nil? || (defined?(CompositePrimaryKeys) && pk.kind_of?(CompositePrimaryKeys::CompositeKeys))
111
- sql = "#{sql} RETURNING #{quote_column_name(pk)} INTO :returning_id"
112
- returning_id_col = OracleEnhancedColumn.new("returning_id", nil, "number", true, "dual", :integer, true, true)
113
- (binds = binds.dup) << [returning_id_col, nil]
114
- end
115
- [sql, binds]
116
- end
117
-
118
- # New method in ActiveRecord 3.1
119
- def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
120
- type_casted_binds = binds.map { |col, val|
121
- [col, type_cast(val, col)]
122
- }
123
- log(sql, name, type_casted_binds) do
124
- returning_id_col = returning_id_index = nil
125
- if without_prepared_statement?(binds)
126
- cursor = @connection.prepare(sql)
127
- else
128
- unless @statements.key? (sql)
129
- @statements[sql] = @connection.prepare(sql)
130
- end
131
-
132
- cursor = @statements[sql]
133
-
134
- binds.each_with_index do |bind, i|
135
- col, val = bind
136
- if col.returning_id?
137
- returning_id_col = [col]
138
- returning_id_index = i + 1
139
- cursor.bind_returning_param(returning_id_index, Integer)
140
- else
141
- cursor.bind_param(i + 1, type_cast(val, col), col)
142
- end
143
- end
144
- end
145
-
146
- cursor.exec_update
147
-
148
- rows = []
149
- if returning_id_index
150
- returning_id = cursor.get_returning_param(returning_id_index, Integer)
151
- rows << [returning_id]
152
- end
153
- ActiveRecord::Result.new(returning_id_col || [], rows)
154
- end
155
- end
156
-
157
- # New method in ActiveRecord 3.1
158
- def exec_update(sql, name, binds)
159
- log(sql, name, binds) do
160
- cached = false
161
- if without_prepared_statement?(binds)
162
- cursor = @connection.prepare(sql)
163
- else
164
- cursor = if @statements.key?(sql)
165
- @statements[sql]
166
- else
167
- @statements[sql] = @connection.prepare(sql)
168
- end
169
-
170
- binds.each_with_index do |bind, i|
171
- col, val = bind
172
- cursor.bind_param(i + 1, type_cast(val, col), col)
173
- end
174
- cached = true
175
- end
176
-
177
- res = cursor.exec_update
178
- cursor.close unless cached
179
- res
180
- end
181
- end
182
-
183
- alias :exec_delete :exec_update
184
-
185
- def begin_db_transaction #:nodoc:
186
- @connection.autocommit = false
187
- end
188
-
189
- def transaction_isolation_levels
190
- # Oracle database supports `READ COMMITTED` and `SERIALIZABLE`
191
- # No read uncommitted nor repeatable read supppoted
192
- # http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10005.htm#SQLRF55422
193
- {
194
- read_committed: "READ COMMITTED",
195
- serializable: "SERIALIZABLE"
196
- }
197
- end
198
-
199
- def begin_isolated_db_transaction(isolation)
200
- begin_db_transaction
201
- execute "SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}"
202
- end
203
-
204
- def commit_db_transaction #:nodoc:
205
- @connection.commit
206
- ensure
207
- @connection.autocommit = true
208
- end
209
-
210
- def rollback_db_transaction #:nodoc:
211
- @connection.rollback
212
- ensure
213
- @connection.autocommit = true
214
- end
215
-
216
- def create_savepoint(name = current_savepoint_name) #:nodoc:
217
- execute("SAVEPOINT #{current_savepoint_name}")
218
- end
219
-
220
- def rollback_to_savepoint(name = current_savepoint_name) #:nodoc:
221
- execute("ROLLBACK TO #{current_savepoint_name}")
222
- end
223
-
224
- def release_savepoint(name = current_savepoint_name) #:nodoc:
225
- # there is no RELEASE SAVEPOINT statement in Oracle
226
- end
227
-
228
- # Returns default sequence name for table.
229
- # Will take all or first 26 characters of table name and append _seq suffix
230
- def default_sequence_name(table_name, primary_key = nil)
231
- table_name.to_s.gsub /(^|\.)([\w$-]{1,#{sequence_name_length-4}})([\w$-]*)$/, '\1\2_seq'
232
- end
233
-
234
- # Inserts the given fixture into the table. Overridden to properly handle lobs.
235
- def insert_fixture(fixture, table_name) #:nodoc:
236
- super
237
-
238
- if ActiveRecord::Base.pluralize_table_names
239
- klass = table_name.to_s.singularize.camelize
240
- else
241
- klass = table_name.to_s.camelize
242
- end
243
-
244
- klass = klass.constantize rescue nil
245
- if klass.respond_to?(:ancestors) && klass.ancestors.include?(ActiveRecord::Base)
246
- write_lobs(table_name, klass, fixture, klass.lob_columns)
247
- end
248
- end
249
-
250
- private
251
-
252
- def select(sql, name = nil, binds = [])
253
- exec_query(sql, name, binds)
254
- end
255
-
256
- end
257
- end
258
- end
259
-
260
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
261
- include ActiveRecord::ConnectionAdapters::OracleEnhancedDatabaseStatements
262
- end
@@ -1,45 +0,0 @@
1
- module ActiveRecord #:nodoc:
2
- module ConnectionAdapters #:nodoc:
3
- module OracleEnhancedDirty #:nodoc:
4
-
5
- module InstanceMethods #:nodoc:
6
- private
7
-
8
- def _field_changed?(attr, old, value)
9
- if column = column_for_attribute(attr)
10
- # Added also :decimal type
11
- if ([:integer, :decimal, :float].include? column.type) && column.null && (old.nil? || old == 0) && value.blank?
12
- # For nullable integer/decimal/float 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
17
- elsif column.type == :string && column.null && old.nil?
18
- # Oracle stores empty string '' as NULL
19
- # therefore need to convert empty string value to nil if old value is nil
20
- value = nil if value == ''
21
- elsif old == 0 && value.is_a?(String) && value.present? && non_zero?(value)
22
- value = nil
23
- else
24
- value = column.type_cast(value)
25
- end
26
- end
27
-
28
- old != value
29
- end
30
-
31
- def non_zero?(value)
32
- value !~ /\A0+(\.0+)?\z/
33
- end
34
-
35
- end
36
-
37
- end
38
- end
39
- end
40
-
41
- if ActiveRecord::Base.method_defined?(:changed?)
42
- ActiveRecord::Base.class_eval do
43
- include ActiveRecord::ConnectionAdapters::OracleEnhancedDirty::InstanceMethods
44
- end
45
- end
@@ -1,197 +0,0 @@
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 OracleEnhancedSchemaDefinitions #:nodoc:
14
- def self.included(base)
15
- base::TableDefinition.class_eval do
16
- include OracleEnhancedTableDefinition
17
- end
18
-
19
- # Available starting from ActiveRecord 2.1
20
- base::Table.class_eval do
21
- include OracleEnhancedTable
22
- end if defined?(base::Table)
23
- end
24
- end
25
-
26
- module OracleEnhancedTableDefinition
27
- class ForeignKey < Struct.new(:base, :to_table, :options) #:nodoc:
28
- def to_sql
29
- base.foreign_key_definition(to_table, options)
30
- end
31
- alias to_s :to_sql
32
- end
33
-
34
- def self.included(base) #:nodoc:
35
- base.class_eval do
36
- alias_method_chain :references, :foreign_keys
37
- alias_method_chain :column, :virtual_columns
38
- end
39
- end
40
-
41
- def raw(name, options={})
42
- column(name, :raw, options)
43
- end
44
-
45
- def virtual(* args)
46
- options = args.extract_options!
47
- column_names = args
48
- column_names.each { |name| column(name, :virtual, options) }
49
- end
50
-
51
- def column_with_virtual_columns(name, type, options = {})
52
- if type == :virtual
53
- default = {:type => options[:type]}
54
- if options[:as]
55
- default[:as] = options[:as]
56
- elsif options[:default]
57
- warn "[DEPRECATION] virtual column `:default` option is deprecated. Please use `:as` instead."
58
- default[:as] = options[:default]
59
- else
60
- raise "No virtual column definition found."
61
- end
62
- options[:default] = default
63
- end
64
- column_without_virtual_columns(name, type, options)
65
- end
66
-
67
- # Adds a :foreign_key option to TableDefinition.references.
68
- # If :foreign_key is true, a foreign key constraint is added to the table.
69
- # You can also specify a hash, which is passed as foreign key options.
70
- #
71
- # ===== Examples
72
- # ====== Add goat_id column and a foreign key to the goats table.
73
- # t.references(:goat, :foreign_key => true)
74
- # ====== Add goat_id column and a cascading foreign key to the goats table.
75
- # t.references(:goat, :foreign_key => {:dependent => :delete})
76
- #
77
- # Note: No foreign key is created if :polymorphic => true is used.
78
- # Note: If no name is specified, the database driver creates one for you!
79
- def references_with_foreign_keys(*args)
80
- options = args.extract_options!
81
- index_options = options[:index]
82
- fk_options = options.delete(:foreign_key)
83
-
84
- if fk_options && !options[:polymorphic]
85
- fk_options = {} if fk_options == true
86
- args.each do |to_table|
87
- foreign_key(to_table, fk_options)
88
- add_index(to_table, "#{to_table}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options
89
- end
90
- end
91
-
92
- references_without_foreign_keys(*(args << options))
93
- end
94
-
95
- # Defines a foreign key for the table. +to_table+ can be a single Symbol, or
96
- # an Array of Symbols. See SchemaStatements#add_foreign_key
97
- #
98
- # ===== Examples
99
- # ====== Creating a simple foreign key
100
- # t.foreign_key(:people)
101
- # ====== Defining the column
102
- # t.foreign_key(:people, :column => :sender_id)
103
- # ====== Creating a named foreign key
104
- # t.foreign_key(:people, :column => :sender_id, :name => 'sender_foreign_key')
105
- # ====== Defining the column of the +to_table+.
106
- # t.foreign_key(:people, :column => :sender_id, :primary_key => :person_id)
107
- def foreign_key(to_table, options = {})
108
- #TODO
109
- if ActiveRecord::Base.connection.supports_foreign_keys?
110
- to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
111
- foreign_keys << ForeignKey.new(@base, to_table, options)
112
- else
113
- raise ArgumentError, "this ActiveRecord adapter is not supporting foreign_key definition"
114
- end
115
- end
116
-
117
- def foreign_keys
118
- @foreign_keys ||= []
119
- end
120
- end
121
-
122
- module OracleEnhancedTable
123
- def self.included(base) #:nodoc:
124
- base.class_eval do
125
- alias_method_chain :references, :foreign_keys
126
- end
127
- end
128
-
129
- # Adds a new foreign key to the table. +to_table+ can be a single Symbol, or
130
- # an Array of Symbols. See SchemaStatements#add_foreign_key
131
- #
132
- # ===== Examples
133
- # ====== Creating a simple foreign key
134
- # t.foreign_key(:people)
135
- # ====== Defining the column
136
- # t.foreign_key(:people, :column => :sender_id)
137
- # ====== Creating a named foreign key
138
- # t.foreign_key(:people, :column => :sender_id, :name => 'sender_foreign_key')
139
- # ====== Defining the column of the +to_table+.
140
- # t.foreign_key(:people, :column => :sender_id, :primary_key => :person_id)
141
- def foreign_key(to_table, options = {})
142
- if @base.respond_to?(:supports_foreign_keys?) && @base.supports_foreign_keys?
143
- to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
144
- @base.add_foreign_key(@table_name, to_table, options)
145
- else
146
- raise ArgumentError, "this ActiveRecord adapter is not supporting foreign_key definition"
147
- end
148
- end
149
-
150
- # Remove the given foreign key from the table.
151
- #
152
- # ===== Examples
153
- # ====== Remove the suppliers_company_id_fk in the suppliers table.
154
- # t.remove_foreign_key :companies
155
- # ====== Remove the foreign key named accounts_branch_id_fk in the accounts table.
156
- # remove_foreign_key :column => :branch_id
157
- # ====== Remove the foreign key named party_foreign_key in the accounts table.
158
- # remove_index :name => :party_foreign_key
159
- def remove_foreign_key(options = {})
160
- @base.remove_foreign_key(@table_name, options)
161
- end
162
-
163
- # Adds a :foreign_key option to TableDefinition.references.
164
- # If :foreign_key is true, a foreign key constraint is added to the table.
165
- # You can also specify a hash, which is passed as foreign key options.
166
- #
167
- # ===== Examples
168
- # ====== Add goat_id column and a foreign key to the goats table.
169
- # t.references(:goat, :foreign_key => true)
170
- # ====== Add goat_id column and a cascading foreign key to the goats table.
171
- # t.references(:goat, :foreign_key => {:dependent => :delete})
172
- #
173
- # Note: No foreign key is created if :polymorphic => true is used.
174
- def references_with_foreign_keys(*args)
175
- options = args.extract_options!
176
- polymorphic = options[:polymorphic]
177
- index_options = options[:index]
178
- fk_options = options.delete(:foreign_key)
179
-
180
- references_without_foreign_keys(*(args << options))
181
- # references_without_foreign_keys adds {:type => :integer}
182
- args.extract_options!
183
- if fk_options && !polymorphic
184
- fk_options = {} if fk_options == true
185
- args.each do |to_table|
186
- foreign_key(to_table, fk_options)
187
- add_index(to_table, "#{to_table}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options
188
- end
189
- end
190
- end
191
- end
192
- end
193
- end
194
-
195
- ActiveRecord::ConnectionAdapters.class_eval do
196
- include ActiveRecord::ConnectionAdapters::OracleEnhancedSchemaDefinitions
197
- end