activerecord-oracle_enhanced-adapter 1.7.11 → 1.8.2

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