pmacs-activerecord-oracle_enhanced-adapter 1.5.6.1 → 1.6.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +7 -7
  3. data/History.md +126 -0
  4. data/README.md +285 -178
  5. data/Rakefile +1 -1
  6. data/VERSION +1 -1
  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_cpk.rb → oracle_enhanced/cpk.rb} +0 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +257 -0
  13. data/lib/active_record/connection_adapters/{oracle_enhanced_database_tasks.rb → oracle_enhanced/database_tasks.rb} +0 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced/dirty.rb +40 -0
  15. data/lib/active_record/connection_adapters/{oracle_enhanced_jdbc_connection.rb → oracle_enhanced/jdbc_connection.rb} +0 -0
  16. data/lib/active_record/connection_adapters/{oracle_enhanced_oci_connection.rb → oracle_enhanced/oci_connection.rb} +0 -0
  17. data/lib/active_record/connection_adapters/{oracle_enhanced_procedures.rb → oracle_enhanced/procedures.rb} +1 -3
  18. data/lib/active_record/connection_adapters/{oracle_enhanced_schema_creation.rb → oracle_enhanced/schema_creation.rb} +34 -35
  19. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +95 -0
  20. data/lib/active_record/connection_adapters/{oracle_enhanced_schema_dumper.rb → oracle_enhanced/schema_dumper.rb} +4 -32
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +548 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +74 -0
  23. data/lib/active_record/connection_adapters/{oracle_enhanced_structure_dump.rb → oracle_enhanced/structure_dump.rb} +28 -6
  24. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -0
  25. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +161 -68
  26. data/lib/active_record/oracle_enhanced/type/integer.rb +13 -0
  27. data/lib/active_record/oracle_enhanced/type/raw.rb +13 -0
  28. data/lib/active_record/oracle_enhanced/type/timestamp.rb +11 -0
  29. data/lib/pmacs-activerecord-oracle_enhanced-adapter.rb +1 -1
  30. data/pmacs-activerecord-oracle_enhanced-adapter.gemspec +35 -31
  31. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +6 -31
  32. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +1 -1
  33. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +2 -2
  34. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +2 -2
  35. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +75 -63
  36. data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +1 -1
  37. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +7 -13
  38. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +2 -1
  39. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +25 -178
  40. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +60 -5
  41. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +1 -0
  42. data/spec/spec_helper.rb +21 -10
  43. metadata +32 -28
  44. data/lib/active_record/connection_adapters/oracle_enhanced_column_dumper.rb +0 -77
  45. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +0 -350
  46. data/lib/active_record/connection_adapters/oracle_enhanced_database_statements.rb +0 -262
  47. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +0 -45
  48. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +0 -223
  49. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +0 -450
  50. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +0 -267
  51. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +0 -1
@@ -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,223 +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 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
- sql_type = base.type_to_sql(default[:type], limit, precision, scale) if default[:type]
24
- "#{base.quote_column_name(name)} #{sql_type} AS (#{default[:as]})"
25
- else
26
- column_sql = to_sql_without_virtual_columns
27
- if type==:primary_key
28
- column_sql << base.table_definition_tablespace
29
- end
30
- end
31
- column_sql
32
- end
33
-
34
- def lob?
35
- ['CLOB', 'BLOB'].include?(sql_type)
36
- end
37
- end
38
-
39
- module OracleEnhancedSchemaDefinitions #:nodoc:
40
- def self.included(base)
41
- base::TableDefinition.class_eval do
42
- include OracleEnhancedTableDefinition
43
- end
44
-
45
- # Available starting from ActiveRecord 2.1
46
- base::Table.class_eval do
47
- include OracleEnhancedTable
48
- end if defined?(base::Table)
49
- end
50
- end
51
-
52
- module OracleEnhancedTableDefinition
53
- class ForeignKey < Struct.new(:base, :to_table, :options) #:nodoc:
54
- def to_sql
55
- base.foreign_key_definition(to_table, options) << base.table_definition_tablespace
56
- end
57
- alias to_s :to_sql
58
- end
59
-
60
- def self.included(base) #:nodoc:
61
- base.class_eval do
62
- alias_method_chain :references, :foreign_keys
63
- alias_method_chain :column, :virtual_columns
64
- end
65
- end
66
-
67
- def raw(name, options={})
68
- column(name, :raw, options)
69
- end
70
-
71
- def virtual(* args)
72
- options = args.extract_options!
73
- column_names = args
74
- column_names.each { |name| column(name, :virtual, options) }
75
- end
76
-
77
- def column_with_virtual_columns(name, type, options = {})
78
- if type == :virtual
79
- default = {:type => options[:type]}
80
- if options[:as]
81
- default[:as] = options[:as]
82
- elsif options[:default]
83
- warn "[DEPRECATION] virtual column `:default` option is deprecated. Please use `:as` instead."
84
- default[:as] = options[:default]
85
- else
86
- raise "No virtual column definition found."
87
- end
88
- options[:default] = default
89
- end
90
- column_without_virtual_columns(name, type, options)
91
- end
92
-
93
- # Adds a :foreign_key option to TableDefinition.references.
94
- # If :foreign_key is true, a foreign key constraint is added to the table.
95
- # You can also specify a hash, which is passed as foreign key options.
96
- #
97
- # ===== Examples
98
- # ====== Add goat_id column and a foreign key to the goats table.
99
- # t.references(:goat, :foreign_key => true)
100
- # ====== Add goat_id column and a cascading foreign key to the goats table.
101
- # t.references(:goat, :foreign_key => {:dependent => :delete})
102
- #
103
- # Note: No foreign key is created if :polymorphic => true is used.
104
- # Note: If no name is specified, the database driver creates one for you!
105
- def references_with_foreign_keys(*args)
106
- options = args.extract_options!
107
- index_options = options[:index]
108
- fk_options = options.delete(:foreign_key)
109
-
110
- if fk_options && !options[:polymorphic]
111
- fk_options = {} if fk_options == true
112
- args.each do |to_table|
113
- foreign_key(to_table, fk_options)
114
- add_index(to_table, "#{to_table}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options
115
- end
116
- end
117
-
118
- references_without_foreign_keys(*(args << options))
119
- end
120
-
121
- # Defines a foreign key for the table. +to_table+ can be a single Symbol, or
122
- # an Array of Symbols. See SchemaStatements#add_foreign_key
123
- #
124
- # ===== Examples
125
- # ====== Creating a simple foreign key
126
- # t.foreign_key(:people)
127
- # ====== Defining the column
128
- # t.foreign_key(:people, :column => :sender_id)
129
- # ====== Creating a named foreign key
130
- # t.foreign_key(:people, :column => :sender_id, :name => 'sender_foreign_key')
131
- # ====== Defining the column of the +to_table+.
132
- # t.foreign_key(:people, :column => :sender_id, :primary_key => :person_id)
133
- def foreign_key(to_table, options = {})
134
- #TODO
135
- if ActiveRecord::Base.connection.supports_foreign_keys?
136
- to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
137
- foreign_keys << ForeignKey.new(@base, to_table, options)
138
- else
139
- raise ArgumentError, "this ActiveRecord adapter is not supporting foreign_key definition"
140
- end
141
- end
142
-
143
- def foreign_keys
144
- @foreign_keys ||= []
145
- end
146
- end
147
-
148
- module OracleEnhancedTable
149
- def self.included(base) #:nodoc:
150
- base.class_eval do
151
- alias_method_chain :references, :foreign_keys
152
- end
153
- end
154
-
155
- # Adds a new foreign key to the table. +to_table+ can be a single Symbol, or
156
- # an Array of Symbols. See SchemaStatements#add_foreign_key
157
- #
158
- # ===== Examples
159
- # ====== Creating a simple foreign key
160
- # t.foreign_key(:people)
161
- # ====== Defining the column
162
- # t.foreign_key(:people, :column => :sender_id)
163
- # ====== Creating a named foreign key
164
- # t.foreign_key(:people, :column => :sender_id, :name => 'sender_foreign_key')
165
- # ====== Defining the column of the +to_table+.
166
- # t.foreign_key(:people, :column => :sender_id, :primary_key => :person_id)
167
- def foreign_key(to_table, options = {})
168
- if @base.respond_to?(:supports_foreign_keys?) && @base.supports_foreign_keys?
169
- to_table = to_table.to_s.pluralize if ActiveRecord::Base.pluralize_table_names
170
- @base.add_foreign_key(@table_name, to_table, options)
171
- else
172
- raise ArgumentError, "this ActiveRecord adapter is not supporting foreign_key definition"
173
- end
174
- end
175
-
176
- # Remove the given foreign key from the table.
177
- #
178
- # ===== Examples
179
- # ====== Remove the suppliers_company_id_fk in the suppliers table.
180
- # t.remove_foreign_key :companies
181
- # ====== Remove the foreign key named accounts_branch_id_fk in the accounts table.
182
- # remove_foreign_key :column => :branch_id
183
- # ====== Remove the foreign key named party_foreign_key in the accounts table.
184
- # remove_index :name => :party_foreign_key
185
- def remove_foreign_key(options = {})
186
- @base.remove_foreign_key(@table_name, options)
187
- end
188
-
189
- # Adds a :foreign_key option to TableDefinition.references.
190
- # If :foreign_key is true, a foreign key constraint is added to the table.
191
- # You can also specify a hash, which is passed as foreign key options.
192
- #
193
- # ===== Examples
194
- # ====== Add goat_id column and a foreign key to the goats table.
195
- # t.references(:goat, :foreign_key => true)
196
- # ====== Add goat_id column and a cascading foreign key to the goats table.
197
- # t.references(:goat, :foreign_key => {:dependent => :delete})
198
- #
199
- # Note: No foreign key is created if :polymorphic => true is used.
200
- def references_with_foreign_keys(*args)
201
- options = args.extract_options!
202
- polymorphic = options[:polymorphic]
203
- index_options = options[:index]
204
- fk_options = options.delete(:foreign_key)
205
-
206
- references_without_foreign_keys(*(args << options))
207
- # references_without_foreign_keys adds {:type => :integer}
208
- args.extract_options!
209
- if fk_options && !polymorphic
210
- fk_options = {} if fk_options == true
211
- args.each do |to_table|
212
- foreign_key(to_table, fk_options)
213
- add_index(to_table, "#{to_table}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options
214
- end
215
- end
216
- end
217
- end
218
- end
219
- end
220
-
221
- ActiveRecord::ConnectionAdapters.class_eval do
222
- include ActiveRecord::ConnectionAdapters::OracleEnhancedSchemaDefinitions
223
- end