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.
- checksums.yaml +4 -4
- data/History.md +288 -0
- data/README.md +44 -0
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +7 -63
- data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +6 -52
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +13 -16
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +117 -119
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +33 -27
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +10 -10
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +59 -77
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +0 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +56 -82
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +4 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +77 -77
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +16 -45
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +60 -65
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +33 -51
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +149 -162
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +119 -122
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +3 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +69 -107
- data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +315 -538
- data/lib/active_record/oracle_enhanced/type/boolean.rb +7 -11
- data/lib/active_record/oracle_enhanced/type/integer.rb +4 -5
- data/lib/active_record/oracle_enhanced/type/json.rb +8 -0
- data/lib/active_record/oracle_enhanced/type/national_character_string.rb +1 -2
- data/lib/active_record/oracle_enhanced/type/raw.rb +2 -4
- data/lib/active_record/oracle_enhanced/type/string.rb +2 -3
- data/lib/active_record/oracle_enhanced/type/text.rb +2 -4
- data/lib/active_record/oracle_enhanced/type/timestamptz.rb +23 -0
- data/lib/activerecord-oracle_enhanced-adapter.rb +14 -13
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +129 -166
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +50 -33
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +44 -42
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +283 -378
- data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +14 -7
- data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +5 -7
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +118 -127
- data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +2 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +74 -78
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +68 -83
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +308 -321
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +103 -48
- data/spec/spec_config.yaml.template +11 -0
- data/spec/spec_helper.rb +59 -60
- data/spec/support/alter_system_user_password.sql +2 -0
- data/spec/support/create_oracle_enhanced_users.sql +31 -0
- metadata +25 -25
- data/.rspec +0 -2
- data/Gemfile +0 -22
- data/RUNNING_TESTS.md +0 -50
- data/Rakefile +0 -45
- data/activerecord-oracle_enhanced-adapter.gemspec +0 -95
- data/lib/active_record/connection_adapters/oracle_enhanced/cpk.rb +0 -21
- 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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
33
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
105
|
-
tbl.print ", temporary: true" if @connection.temporary_table?(table)
|
|
78
|
+
return if add_index_statements.empty?
|
|
106
79
|
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
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
|
-
|
|
129
|
-
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
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
|
-
|
|
148
|
-
|
|
116
|
+
# addition to make temporary option work
|
|
117
|
+
tbl.print ", temporary: true" if @connection.temporary_table?(table)
|
|
149
118
|
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
154
|
-
format_string.unshift " t.%-#{type_length}s "
|
|
133
|
+
tbl.print ", force: :cascade"
|
|
155
134
|
|
|
156
|
-
|
|
135
|
+
table_comments = @connection.table_comment(table)
|
|
136
|
+
unless table_comments.blank?
|
|
137
|
+
tbl.print ", comment: #{table_comments.inspect}"
|
|
138
|
+
end
|
|
157
139
|
|
|
158
|
-
|
|
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
|
-
|
|
167
|
-
|
|
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
|
-
|
|
152
|
+
indexes_in_create(table, tbl)
|
|
170
153
|
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
180
|
-
end
|
|
157
|
+
indexes(table, tbl)
|
|
181
158
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
187
|
-
module TableInspect #:nodoc:
|
|
188
|
-
def inspect
|
|
189
|
-
remove_prefix_and_suffix(self)
|
|
167
|
+
stream
|
|
190
168
|
end
|
|
191
169
|
|
|
192
|
-
|
|
193
|
-
|
|
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
|