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.
- checksums.yaml +4 -4
- data/History.md +206 -4
- data/README.md +37 -1
- 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 -59
- data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +6 -50
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +11 -11
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +117 -117
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +37 -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 +56 -71
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +0 -7
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +51 -69
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +4 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +76 -76
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +14 -43
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +60 -64
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +33 -47
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +150 -160
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +95 -133
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +66 -101
- data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +290 -533
- data/lib/active_record/oracle_enhanced/type/boolean.rb +7 -10
- data/lib/active_record/oracle_enhanced/type/integer.rb +3 -4
- data/lib/active_record/oracle_enhanced/type/json.rb +8 -0
- data/lib/active_record/oracle_enhanced/type/national_character_string.rb +1 -1
- data/lib/active_record/oracle_enhanced/type/raw.rb +2 -3
- data/lib/active_record/oracle_enhanced/type/string.rb +2 -2
- data/lib/active_record/oracle_enhanced/type/text.rb +2 -2
- data/lib/active_record/oracle_enhanced/type/timestamptz.rb +23 -0
- data/lib/activerecord-oracle_enhanced-adapter.rb +2 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +55 -162
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +32 -34
- 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 +250 -357
- data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +14 -6
- data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +3 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +115 -124
- 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 +68 -72
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +64 -80
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +223 -329
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +18 -20
- data/spec/spec_config.yaml.template +11 -0
- data/spec/spec_helper.rb +59 -59
- 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 -83
- data/Rakefile +0 -45
- data/activerecord-oracle_enhanced-adapter.gemspec +0 -94
- data/lib/active_record/connection_adapters/oracle_enhanced/cpk.rb +0 -19
- 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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
32
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
104
|
-
tbl.print ", temporary: true" if @connection.temporary_table?(table)
|
78
|
+
return if add_index_statements.empty?
|
105
79
|
|
106
|
-
|
107
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
-
|
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
|
-
|
128
|
-
|
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
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
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
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
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
|
-
|
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
|
-
|
147
|
-
|
117
|
+
# addition to make temporary option work
|
118
|
+
tbl.print ", temporary: true" if @connection.temporary_table?(table)
|
148
119
|
|
149
|
-
|
150
|
-
|
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
|
-
|
153
|
-
format_string.unshift " t.%-#{type_length}s "
|
134
|
+
tbl.print ", force: :cascade"
|
154
135
|
|
155
|
-
|
136
|
+
table_comments = @connection.table_comment(table)
|
137
|
+
unless table_comments.blank?
|
138
|
+
tbl.print ", comment: #{table_comments.inspect}"
|
139
|
+
end
|
156
140
|
|
157
|
-
|
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
|
-
|
166
|
-
|
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
|
-
|
153
|
+
indexes_in_create(table, tbl)
|
169
154
|
|
170
|
-
|
171
|
-
|
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
|
-
|
179
|
-
end
|
158
|
+
indexes(table, tbl)
|
180
159
|
|
181
|
-
|
182
|
-
|
183
|
-
|
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
|
-
|
186
|
-
|
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
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
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
|