activerecord-oracle_enhanced-adapter 1.7.3 → 1.8.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +288 -0
  3. data/README.md +44 -0
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +1 -1
  6. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +7 -63
  7. data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +6 -52
  8. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +13 -16
  9. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +117 -119
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +33 -27
  11. data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +10 -10
  12. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +59 -77
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +0 -4
  14. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +56 -82
  15. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +4 -4
  16. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +77 -77
  17. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +16 -45
  18. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +60 -65
  19. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +33 -51
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +149 -162
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +119 -122
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +3 -4
  23. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +69 -107
  24. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -1
  25. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +315 -538
  26. data/lib/active_record/oracle_enhanced/type/boolean.rb +7 -11
  27. data/lib/active_record/oracle_enhanced/type/integer.rb +4 -5
  28. data/lib/active_record/oracle_enhanced/type/json.rb +8 -0
  29. data/lib/active_record/oracle_enhanced/type/national_character_string.rb +1 -2
  30. data/lib/active_record/oracle_enhanced/type/raw.rb +2 -4
  31. data/lib/active_record/oracle_enhanced/type/string.rb +2 -3
  32. data/lib/active_record/oracle_enhanced/type/text.rb +2 -4
  33. data/lib/active_record/oracle_enhanced/type/timestamptz.rb +23 -0
  34. data/lib/activerecord-oracle_enhanced-adapter.rb +14 -13
  35. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +129 -166
  36. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +50 -33
  37. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +44 -42
  38. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +283 -378
  39. data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +14 -7
  40. data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +5 -7
  41. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +118 -127
  42. data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +2 -3
  43. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +74 -78
  44. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +68 -83
  45. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +308 -321
  46. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +103 -48
  47. data/spec/spec_config.yaml.template +11 -0
  48. data/spec/spec_helper.rb +59 -60
  49. data/spec/support/alter_system_user_password.sql +2 -0
  50. data/spec/support/create_oracle_enhanced_users.sql +31 -0
  51. metadata +25 -25
  52. data/.rspec +0 -2
  53. data/Gemfile +0 -22
  54. data/RUNNING_TESTS.md +0 -50
  55. data/Rakefile +0 -45
  56. data/activerecord-oracle_enhanced-adapter.gemspec +0 -95
  57. data/lib/active_record/connection_adapters/oracle_enhanced/cpk.rb +0 -21
  58. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
@@ -2,203 +2,190 @@ module ActiveRecord #:nodoc:
2
2
  module ConnectionAdapters #:nodoc:
3
3
  module OracleEnhanced #:nodoc:
4
4
  module SchemaDumper #:nodoc:
5
-
6
5
  private
7
6
 
8
- def tables(stream)
9
- return super unless @connection.respond_to?(:materialized_views)
10
- # do not include materialized views in schema dump - they should be created separately after schema creation
11
- sorted_tables = (@connection.data_sources - @connection.materialized_views).sort
12
- sorted_tables.each do |tbl|
13
- # add table prefix or suffix for schema_migrations
14
- next if ignored? tbl
15
- # change table name inspect method
16
- tbl.extend TableInspect
17
- table(tbl, stream)
18
- # add primary key trigger if table has it
19
- primary_key_trigger(tbl, stream)
20
- end
21
- # following table definitions
22
- # add foreign keys if table has them
23
- sorted_tables.each do |tbl|
24
- next if ignored? tbl
25
- foreign_keys(tbl, stream)
26
- end
27
-
28
- # add synonyms in local schema
29
- synonyms(stream)
30
- end
7
+ def tables(stream)
8
+ return super unless @connection.respond_to?(:materialized_views)
9
+ # do not include materialized views in schema dump - they should be created separately after schema creation
10
+ sorted_tables = (@connection.tables - @connection.materialized_views).sort
11
+ sorted_tables.each do |tbl|
12
+ # add table prefix or suffix for schema_migrations
13
+ next if ignored? tbl
14
+ # change table name inspect method
15
+ tbl.extend TableInspect
16
+ table(tbl, stream)
17
+ # add primary key trigger if table has it
18
+ primary_key_trigger(tbl, stream)
19
+ end
20
+ # following table definitions
21
+ # add foreign keys if table has them
22
+ sorted_tables.each do |tbl|
23
+ next if ignored? tbl
24
+ foreign_keys(tbl, stream)
25
+ end
31
26
 
32
- def primary_key_trigger(table_name, stream)
33
- if @connection.respond_to?(:has_primary_key_trigger?) && @connection.has_primary_key_trigger?(table_name)
34
- pk, _pk_seq = @connection.pk_and_sequence_for(table_name)
35
- stream.print " add_primary_key_trigger #{table_name.inspect}"
36
- stream.print ", primary_key: \"#{pk}\"" if pk != 'id'
37
- stream.print "\n\n"
27
+ # add synonyms in local schema
28
+ synonyms(stream)
38
29
  end
39
- end
40
-
41
- def synonyms(stream)
42
- if @connection.respond_to?(:synonyms)
43
- syns = @connection.synonyms
44
- syns.each do |syn|
45
- next if ignored? syn.name
46
- table_name = syn.table_name
47
- table_name = "#{syn.table_owner}.#{table_name}" if syn.table_owner
48
- table_name = "#{table_name}@#{syn.db_link}" if syn.db_link
49
- stream.print " add_synonym #{syn.name.inspect}, #{table_name.inspect}, force: true"
50
- stream.puts
30
+
31
+ def primary_key_trigger(table_name, stream)
32
+ if @connection.respond_to?(:has_primary_key_trigger?) && @connection.has_primary_key_trigger?(table_name)
33
+ pk, _pk_seq = @connection.pk_and_sequence_for(table_name)
34
+ stream.print " add_primary_key_trigger #{table_name.inspect}"
35
+ stream.print ", primary_key: \"#{pk}\"" if pk != "id"
36
+ stream.print "\n\n"
51
37
  end
52
- stream.puts unless syns.empty?
53
38
  end
54
- end
55
-
56
- def indexes(table, stream)
57
- if (indexes = @connection.indexes(table)).any?
58
- add_index_statements = indexes.map do |index|
59
- case index.type
60
- when nil
61
- # use table.inspect as it will remove prefix and suffix
62
- statement_parts = [ ('add_index ' + table.inspect) ]
63
- statement_parts << index.columns.inspect
64
- statement_parts << ('name: ' + index.name.inspect)
65
- statement_parts << 'unique: true' if index.unique
66
- statement_parts << 'tablespace: ' + index.tablespace.inspect if index.tablespace
67
- when 'CTXSYS.CONTEXT'
68
- if index.statement_parameters
69
- statement_parts = [ ('add_context_index ' + table.inspect) ]
70
- statement_parts << index.statement_parameters
71
- else
72
- statement_parts = [ ('add_context_index ' + table.inspect) ]
73
- statement_parts << index.columns.inspect
74
- statement_parts << ('name: ' + index.name.inspect)
75
- end
76
- else
77
- # unrecognized index type
78
- statement_parts = ["# unrecognized index #{index.name.inspect} with type #{index.type.inspect}"]
39
+
40
+ def synonyms(stream)
41
+ if @connection.respond_to?(:synonyms)
42
+ syns = @connection.synonyms
43
+ syns.each do |syn|
44
+ next if ignored? syn.name
45
+ table_name = syn.table_name
46
+ table_name = "#{syn.table_owner}.#{table_name}" if syn.table_owner
47
+ table_name = "#{table_name}@#{syn.db_link}" if syn.db_link
48
+ stream.print " add_synonym #{syn.name.inspect}, #{table_name.inspect}, force: true"
49
+ stream.puts
79
50
  end
80
- ' ' + statement_parts.join(', ')
51
+ stream.puts unless syns.empty?
81
52
  end
82
-
83
- stream.puts add_index_statements.sort.join("\n")
84
- stream.puts
85
53
  end
86
- end
87
-
88
- def table(table, stream)
89
- return super unless @connection.respond_to?(:temporary_table?)
90
- columns = @connection.columns(table)
91
- begin
92
- tbl = StringIO.new
93
-
94
- # first dump primary key column
95
- if @connection.respond_to?(:primary_keys)
96
- pk = @connection.primary_keys(table)
97
- pk = pk.first unless pk.size > 1
98
- else
99
- pk = @connection.primary_key(table)
100
- end
101
54
 
102
- tbl.print " create_table #{table.inspect}"
55
+ def indexes(table, stream)
56
+ if (indexes = @connection.indexes(table)).any?
57
+ add_index_statements = indexes.map do |index|
58
+ case index.type
59
+ when nil
60
+ # do nothing here. see indexes_in_create
61
+ statement_parts = []
62
+ when "CTXSYS.CONTEXT"
63
+ if index.statement_parameters
64
+ statement_parts = [ ("add_context_index " + table.inspect) ]
65
+ statement_parts << index.statement_parameters
66
+ else
67
+ statement_parts = [ ("add_context_index " + table.inspect) ]
68
+ statement_parts << index.columns.inspect
69
+ statement_parts << ("name: " + index.name.inspect)
70
+ end
71
+ else
72
+ # unrecognized index type
73
+ statement_parts = ["# unrecognized index #{index.name.inspect} with type #{index.type.inspect}"]
74
+ end
75
+ " " + statement_parts.join(", ") unless statement_parts.empty?
76
+ end.compact
103
77
 
104
- # addition to make temporary option work
105
- tbl.print ", temporary: true" if @connection.temporary_table?(table)
78
+ return if add_index_statements.empty?
106
79
 
107
- table_comments = @connection.table_comment(table)
108
- unless table_comments.nil?
109
- tbl.print ", comment: #{table_comments.inspect}"
80
+ stream.puts add_index_statements.sort.join("\n")
81
+ stream.puts
110
82
  end
83
+ end
111
84
 
112
- case pk
113
- when String
114
- tbl.print ", primary_key: #{pk.inspect}" unless pk == 'id'
115
- pkcol = columns.detect { |c| c.name == pk }
116
- pkcolspec = @connection.column_spec_for_primary_key(pkcol)
117
- if pkcolspec.present?
118
- pkcolspec.each do |key, value|
119
- tbl.print ", #{key}: #{value}"
120
- end
85
+ def indexes_in_create(table, stream)
86
+ if (indexes = @connection.indexes(table)).any?
87
+ index_statements = indexes.map do |index|
88
+ " t.index #{index_parts(index).join(', ')}" unless index.type == "CTXSYS.CONTEXT"
121
89
  end
122
- when Array
123
- tbl.print ", primary_key: #{pk.inspect}"
124
- else
125
- tbl.print ", id: false"
90
+ stream.puts index_statements.sort.join("\n")
126
91
  end
92
+ end
127
93
 
128
- tbl.print ", force: :cascade"
129
- tbl.puts " do |t|"
94
+ def index_parts(index)
95
+ index_parts = super
96
+ index_parts << "tablespace: #{index.tablespace.inspect}" if index.tablespace
97
+ index_parts
98
+ end
130
99
 
131
- # then dump all non-primary key columns
132
- column_specs = columns.map do |column|
133
- raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
134
- next if column.name == pk
135
- @connection.column_spec(column)
136
- end.compact
100
+ def table(table, stream)
101
+ return super unless @connection.respond_to?(:temporary_table?)
102
+ columns = @connection.columns(table)
103
+ begin
104
+ tbl = StringIO.new
137
105
 
138
- # find all migration keys used in this table
139
- #
140
- # TODO `& column_specs.map(&:keys).flatten` should be executed
141
- # in migration_keys_with_oracle_enhanced
142
- keys = @connection.migration_keys & column_specs.map(&:keys).flatten
106
+ # first dump primary key column
107
+ if @connection.respond_to?(:primary_keys)
108
+ pk = @connection.primary_keys(table)
109
+ pk = pk.first unless pk.size > 1
110
+ else
111
+ pk = @connection.primary_key(table)
112
+ end
143
113
 
144
- # figure out the lengths for each column based on above keys
145
- lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max }
114
+ tbl.print " create_table #{table.inspect}"
146
115
 
147
- # the string we're going to sprintf our values against, with standardized column widths
148
- format_string = lengths.map{ |len| "%-#{len}s" }
116
+ # addition to make temporary option work
117
+ tbl.print ", temporary: true" if @connection.temporary_table?(table)
149
118
 
150
- # find the max length for the 'type' column, which is special
151
- type_length = column_specs.map{ |column| column[:type].length }.max
119
+ case pk
120
+ when String
121
+ tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
122
+ pkcol = columns.detect { |c| c.name == pk }
123
+ pkcolspec = @connection.column_spec_for_primary_key(pkcol)
124
+ if pkcolspec.present?
125
+ tbl.print ", #{format_colspec(pkcolspec)}"
126
+ end
127
+ when Array
128
+ tbl.print ", primary_key: #{pk.inspect}"
129
+ else
130
+ tbl.print ", id: false"
131
+ end
152
132
 
153
- # add column type definition to our format string
154
- format_string.unshift " t.%-#{type_length}s "
133
+ tbl.print ", force: :cascade"
155
134
 
156
- format_string *= ''
135
+ table_comments = @connection.table_comment(table)
136
+ unless table_comments.blank?
137
+ tbl.print ", comment: #{table_comments.inspect}"
138
+ end
157
139
 
158
- # dirty hack to replace virtual_type: with type:
159
- column_specs.each do |colspec|
160
- values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len }
161
- values.unshift colspec[:type]
162
- tbl.print((format_string % values).gsub(/,\s*$/, '').gsub(/virtual_type:/, "type:"))
163
- tbl.puts
164
- end
140
+ tbl.puts " do |t|"
165
141
 
166
- tbl.puts " end"
167
- tbl.puts
142
+ # then dump all non-primary key columns
143
+ columns.each do |column|
144
+ raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
145
+ next if column.name == pk
146
+ type, colspec = @connection.column_spec(column)
147
+ tbl.print " t.#{type} #{column.name.inspect}"
148
+ tbl.print ", #{format_colspec(colspec)}" if colspec.present?
149
+ tbl.puts
150
+ end
168
151
 
169
- indexes(table, tbl)
152
+ indexes_in_create(table, tbl)
170
153
 
171
- tbl.rewind
172
- stream.print tbl.read
173
- rescue => e
174
- stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
175
- stream.puts "# #{e.message}"
176
- stream.puts
177
- end
154
+ tbl.puts " end"
155
+ tbl.puts
178
156
 
179
- stream
180
- end
157
+ indexes(table, tbl)
181
158
 
182
- def remove_prefix_and_suffix(table)
183
- table.gsub(/^(#{ActiveRecord::Base.table_name_prefix})(.+)(#{ActiveRecord::Base.table_name_suffix})$/, "\\2")
184
- end
159
+ tbl.rewind
160
+ stream.print tbl.read
161
+ rescue => e
162
+ stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
163
+ stream.puts "# #{e.message}"
164
+ stream.puts
165
+ end
185
166
 
186
- # remove table name prefix and suffix when doing #inspect (which is used in tables method)
187
- module TableInspect #:nodoc:
188
- def inspect
189
- remove_prefix_and_suffix(self)
167
+ stream
190
168
  end
191
169
 
192
- private
193
- def remove_prefix_and_suffix(table_name)
194
- if table_name =~ /\A#{ActiveRecord::Base.table_name_prefix.to_s.gsub('$','\$')}(.*)#{ActiveRecord::Base.table_name_suffix.to_s.gsub('$','\$')}\Z/
195
- "\"#{$1}\""
196
- else
197
- "\"#{table_name}\""
198
- end
170
+ def remove_prefix_and_suffix(table)
171
+ table.gsub(/^(#{ActiveRecord::Base.table_name_prefix})(.+)(#{ActiveRecord::Base.table_name_suffix})$/, "\\2")
199
172
  end
200
- end
201
173
 
174
+ # remove table name prefix and suffix when doing #inspect (which is used in tables method)
175
+ module TableInspect #:nodoc:
176
+ def inspect
177
+ remove_prefix_and_suffix(self)
178
+ end
179
+
180
+ private
181
+ def remove_prefix_and_suffix(table_name)
182
+ if table_name =~ /\A#{ActiveRecord::Base.table_name_prefix.to_s.gsub('$', '\$')}(.*)#{ActiveRecord::Base.table_name_suffix.to_s.gsub('$', '\$')}\Z/
183
+ "\"#{$1}\""
184
+ else
185
+ "\"#{table_name}\""
186
+ end
187
+ end
188
+ end
202
189
  end
203
190
  end
204
191
  end