activerecord-oracle_enhanced-adapter 1.5.6 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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