activerecord-oracle_enhanced-adapter 8.1.0-java
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 +7 -0
- data/History.md +1971 -0
- data/License.txt +20 -0
- data/README.md +947 -0
- data/VERSION +1 -0
- data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +7 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +24 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +137 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +359 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +47 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +325 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +63 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +71 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +629 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +38 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +57 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +465 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +44 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +195 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +186 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +95 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +99 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +197 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +739 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +394 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +34 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +3 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +886 -0
- data/lib/active_record/type/oracle_enhanced/boolean.rb +19 -0
- data/lib/active_record/type/oracle_enhanced/character_string.rb +36 -0
- data/lib/active_record/type/oracle_enhanced/integer.rb +14 -0
- data/lib/active_record/type/oracle_enhanced/json.rb +10 -0
- data/lib/active_record/type/oracle_enhanced/national_character_string.rb +26 -0
- data/lib/active_record/type/oracle_enhanced/national_character_text.rb +36 -0
- data/lib/active_record/type/oracle_enhanced/raw.rb +25 -0
- data/lib/active_record/type/oracle_enhanced/string.rb +29 -0
- data/lib/active_record/type/oracle_enhanced/text.rb +32 -0
- data/lib/active_record/type/oracle_enhanced/timestampltz.rb +25 -0
- data/lib/active_record/type/oracle_enhanced/timestamptz.rb +25 -0
- data/lib/activerecord-oracle_enhanced-adapter.rb +25 -0
- data/lib/arel/visitors/oracle.rb +216 -0
- data/lib/arel/visitors/oracle12.rb +121 -0
- data/lib/arel/visitors/oracle_common.rb +51 -0
- data/spec/active_record/connection_adapters/emulation/oracle_adapter_spec.rb +24 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/compatibility_spec.rb +40 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/composite_spec.rb +84 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +589 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb +431 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +122 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/dbconsole_spec.rb +63 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/dbms_output_spec.rb +69 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +362 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +181 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +492 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +1318 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +485 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +815 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +230 -0
- data/spec/active_record/oracle_enhanced/type/binary_spec.rb +119 -0
- data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +206 -0
- data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +67 -0
- data/spec/active_record/oracle_enhanced/type/custom_spec.rb +90 -0
- data/spec/active_record/oracle_enhanced/type/decimal_spec.rb +56 -0
- data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +141 -0
- data/spec/active_record/oracle_enhanced/type/float_spec.rb +48 -0
- data/spec/active_record/oracle_enhanced/type/integer_spec.rb +101 -0
- data/spec/active_record/oracle_enhanced/type/json_spec.rb +56 -0
- data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +55 -0
- data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +230 -0
- data/spec/active_record/oracle_enhanced/type/raw_spec.rb +137 -0
- data/spec/active_record/oracle_enhanced/type/text_spec.rb +295 -0
- data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +107 -0
- data/spec/spec_config.yaml.template +11 -0
- data/spec/spec_helper.rb +225 -0
- data/spec/support/alter_system_set_open_cursors.sql +1 -0
- data/spec/support/alter_system_user_password.sql +2 -0
- data/spec/support/create_oracle_enhanced_users.sql +31 -0
- metadata +181 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord # :nodoc:
|
|
4
|
+
module ConnectionAdapters # :nodoc:
|
|
5
|
+
module OracleEnhanced # :nodoc:
|
|
6
|
+
module StructureDump # :nodoc:
|
|
7
|
+
# Statements separator used in structure dump to allow loading of structure dump also with SQL*Plus
|
|
8
|
+
STATEMENT_TOKEN = "\n\n/\n\n"
|
|
9
|
+
|
|
10
|
+
def structure_dump # :nodoc:
|
|
11
|
+
sequences = select(<<~SQL.squish, "SCHEMA")
|
|
12
|
+
SELECT
|
|
13
|
+
sequence_name, min_value, max_value, increment_by, order_flag, cycle_flag
|
|
14
|
+
FROM all_sequences
|
|
15
|
+
where sequence_owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
|
|
16
|
+
SQL
|
|
17
|
+
|
|
18
|
+
structure = sequences.map do |result|
|
|
19
|
+
"CREATE SEQUENCE #{quote_table_name(result["sequence_name"])} MINVALUE #{result["min_value"]} MAXVALUE #{result["max_value"]} INCREMENT BY #{result["increment_by"]} #{result["order_flag"] == 'Y' ? "ORDER" : "NOORDER"} #{result["cycle_flag"] == 'Y' ? "CYCLE" : "NOCYCLE"}"
|
|
20
|
+
end
|
|
21
|
+
tables = select_values(<<~SQL.squish, "SCHEMA")
|
|
22
|
+
SELECT table_name FROM all_tables t
|
|
23
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'
|
|
24
|
+
AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv
|
|
25
|
+
WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
|
|
26
|
+
AND NOT EXISTS (SELECT mvl.log_table FROM all_mview_logs mvl
|
|
27
|
+
WHERE mvl.log_owner = t.owner AND mvl.log_table = t.table_name)
|
|
28
|
+
ORDER BY 1
|
|
29
|
+
SQL
|
|
30
|
+
tables.each do |table_name|
|
|
31
|
+
virtual_columns = virtual_columns_for(table_name) if supports_virtual_columns?
|
|
32
|
+
ddl = +"CREATE#{ ' GLOBAL TEMPORARY' if temporary_table?(table_name)} TABLE \"#{table_name}\" (\n"
|
|
33
|
+
columns = select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
|
|
34
|
+
SELECT column_name, data_type, data_length, char_used, char_length,
|
|
35
|
+
data_precision, data_scale, data_default, nullable
|
|
36
|
+
FROM all_tab_columns
|
|
37
|
+
WHERE table_name = :table_name
|
|
38
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
39
|
+
ORDER BY column_id
|
|
40
|
+
SQL
|
|
41
|
+
cols = columns.map do |row|
|
|
42
|
+
if (v = virtual_columns.find { |col| col["column_name"] == row["column_name"] })
|
|
43
|
+
structure_dump_virtual_column(row, v["data_default"])
|
|
44
|
+
else
|
|
45
|
+
structure_dump_column(row)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
ddl << cols.map { |col| " #{col}" }.join(",\n")
|
|
49
|
+
ddl << structure_dump_primary_key(table_name)
|
|
50
|
+
ddl << "\n)"
|
|
51
|
+
structure << ddl
|
|
52
|
+
structure << structure_dump_indexes(table_name)
|
|
53
|
+
structure << structure_dump_unique_keys(table_name)
|
|
54
|
+
structure << structure_dump_check_constraints(table_name)
|
|
55
|
+
structure << structure_dump_table_comments(table_name)
|
|
56
|
+
structure << structure_dump_column_comments(table_name)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
join_with_statement_token(structure) <<
|
|
60
|
+
structure_dump_fk_constraints <<
|
|
61
|
+
structure_dump_views
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def structure_dump_column(column) # :nodoc:
|
|
65
|
+
col = +"\"#{column['column_name']}\" #{column['data_type']}"
|
|
66
|
+
if (column["data_type"] == "NUMBER") && !column["data_precision"].nil?
|
|
67
|
+
col << "(#{column['data_precision'].to_i}"
|
|
68
|
+
col << ",#{column['data_scale'].to_i}" if !column["data_scale"].nil?
|
|
69
|
+
col << ")"
|
|
70
|
+
elsif column["data_type"].include?("CHAR") || column["data_type"] == "RAW"
|
|
71
|
+
length = column["char_used"] == "C" ? column["char_length"].to_i : column["data_length"].to_i
|
|
72
|
+
col << "(#{length})"
|
|
73
|
+
end
|
|
74
|
+
col << " DEFAULT #{column['data_default']}" if !column["data_default"].nil?
|
|
75
|
+
col << " NOT NULL" if column["nullable"] == "N"
|
|
76
|
+
col
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def structure_dump_virtual_column(column, data_default) # :nodoc:
|
|
80
|
+
data_default = data_default.delete('"')
|
|
81
|
+
col = +"\"#{column['column_name']}\" #{column['data_type']}"
|
|
82
|
+
if (column["data_type"] == "NUMBER") && !column["data_precision"].nil?
|
|
83
|
+
col << "(#{column['data_precision'].to_i}"
|
|
84
|
+
col << ",#{column['data_scale'].to_i}" if !column["data_scale"].nil?
|
|
85
|
+
col << ")"
|
|
86
|
+
elsif column["data_type"].include?("CHAR") || column["data_type"] == "RAW"
|
|
87
|
+
length = column["char_used"] == "C" ? column["char_length"].to_i : column["data_length"].to_i
|
|
88
|
+
col << "(#{length})"
|
|
89
|
+
end
|
|
90
|
+
col << " GENERATED ALWAYS AS (#{data_default}) VIRTUAL"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def structure_dump_primary_key(table) # :nodoc:
|
|
94
|
+
opts = { name: "", cols: [] }
|
|
95
|
+
pks = select_all(<<~SQL.squish, "SCHEMA")
|
|
96
|
+
SELECT a.constraint_name, a.column_name, a.position
|
|
97
|
+
FROM all_cons_columns a
|
|
98
|
+
JOIN all_constraints c
|
|
99
|
+
ON a.constraint_name = c.constraint_name
|
|
100
|
+
WHERE c.table_name = '#{table.upcase}'
|
|
101
|
+
AND c.constraint_type = 'P'
|
|
102
|
+
AND a.owner = c.owner
|
|
103
|
+
AND c.owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
104
|
+
SQL
|
|
105
|
+
pks.each do |row|
|
|
106
|
+
opts[:name] = row["constraint_name"]
|
|
107
|
+
opts[:cols][row["position"] - 1] = row["column_name"]
|
|
108
|
+
end
|
|
109
|
+
opts[:cols].length > 0 ? ",\n CONSTRAINT #{opts[:name]} PRIMARY KEY (#{opts[:cols].join(',')})" : ""
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def structure_dump_unique_keys(table) # :nodoc:
|
|
113
|
+
keys = {}
|
|
114
|
+
uks = select_all(<<~SQL.squish, "SCHEMA")
|
|
115
|
+
SELECT a.constraint_name, a.column_name, a.position
|
|
116
|
+
FROM all_cons_columns a
|
|
117
|
+
JOIN all_constraints c
|
|
118
|
+
ON a.constraint_name = c.constraint_name
|
|
119
|
+
WHERE c.table_name = '#{table.upcase}'
|
|
120
|
+
AND c.constraint_type = 'U'
|
|
121
|
+
AND a.owner = c.owner
|
|
122
|
+
AND c.owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
123
|
+
SQL
|
|
124
|
+
uks.each do |uk|
|
|
125
|
+
keys[uk["constraint_name"]] ||= []
|
|
126
|
+
keys[uk["constraint_name"]][uk["position"] - 1] = uk["column_name"]
|
|
127
|
+
end
|
|
128
|
+
keys.map do |k, v|
|
|
129
|
+
"ALTER TABLE #{table.upcase} ADD CONSTRAINT #{k} UNIQUE (#{v.join(',')})"
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def structure_dump_indexes(table_name) # :nodoc:
|
|
134
|
+
indexes(table_name).map do |options|
|
|
135
|
+
column_names = options.columns
|
|
136
|
+
options = { name: options.name, unique: options.unique }
|
|
137
|
+
index_name = index_name(table_name, column: column_names)
|
|
138
|
+
if Hash === options # legacy support, since this param was a string
|
|
139
|
+
index_type = options[:unique] ? "UNIQUE" : ""
|
|
140
|
+
index_name = options[:name] || index_name
|
|
141
|
+
else
|
|
142
|
+
index_type = options
|
|
143
|
+
end
|
|
144
|
+
quoted_column_names = column_names.map { |e| quote_column_name_or_expression(e) }.join(", ")
|
|
145
|
+
"CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def structure_dump_fk_constraints # :nodoc:
|
|
150
|
+
foreign_keys = select_all(<<~SQL.squish, "SCHEMA")
|
|
151
|
+
SELECT table_name FROM all_tables
|
|
152
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
|
|
153
|
+
SQL
|
|
154
|
+
fks = foreign_keys.map do |table|
|
|
155
|
+
if respond_to?(:foreign_keys) && (foreign_keys = foreign_keys(table["table_name"])).any?
|
|
156
|
+
foreign_keys.map do |fk|
|
|
157
|
+
sql = +"ALTER TABLE #{quote_table_name(fk.from_table)} ADD CONSTRAINT #{quote_column_name(fk.options[:name])} "
|
|
158
|
+
sql << "#{foreign_key_definition(fk.to_table, fk.options)}"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end.flatten.compact
|
|
162
|
+
join_with_statement_token(fks)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Only user-named CHECK constraints are preserved. Anonymous
|
|
166
|
+
# constraints created via `ALTER TABLE ... ADD CHECK (...)` receive
|
|
167
|
+
# Oracle-generated names (e.g. SYS_C00123) and are skipped to avoid
|
|
168
|
+
# also emitting the implicit NOT NULL check constraints that Oracle
|
|
169
|
+
# stores with constraint_type = 'C'.
|
|
170
|
+
def structure_dump_check_constraints(table_name) # :nodoc:
|
|
171
|
+
# `search_condition` is a LONG column, so it cannot appear in a
|
|
172
|
+
# WHERE clause (ORA-00997). The driver reads it as a String on
|
|
173
|
+
# SELECT. Implicit NOT NULL constraints Oracle stores with
|
|
174
|
+
# constraint_type = 'C' are excluded by `generated = 'USER NAME'`
|
|
175
|
+
# since they receive system-generated names.
|
|
176
|
+
check_constraints = select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name.upcase)])
|
|
177
|
+
SELECT constraint_name, search_condition
|
|
178
|
+
FROM all_constraints
|
|
179
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
180
|
+
AND table_name = :table_name
|
|
181
|
+
AND constraint_type = 'C'
|
|
182
|
+
AND generated = 'USER NAME'
|
|
183
|
+
ORDER BY constraint_name
|
|
184
|
+
SQL
|
|
185
|
+
check_constraints.filter_map do |row|
|
|
186
|
+
condition = row["search_condition"]
|
|
187
|
+
next if condition.nil?
|
|
188
|
+
"ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{quote_column_name(row["constraint_name"])} CHECK (#{condition})"
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def structure_dump_table_comments(table_name)
|
|
193
|
+
comments = []
|
|
194
|
+
comment = table_comment(table_name)
|
|
195
|
+
|
|
196
|
+
unless comment.nil?
|
|
197
|
+
comments << "COMMENT ON TABLE #{quote_table_name(table_name)} IS '#{quote_string(comment)}'"
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
join_with_statement_token(comments)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def structure_dump_column_comments(table_name)
|
|
204
|
+
comments = []
|
|
205
|
+
columns = select_values(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
|
|
206
|
+
SELECT column_name FROM all_tab_columns
|
|
207
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
208
|
+
AND table_name = :table_name ORDER BY column_id
|
|
209
|
+
SQL
|
|
210
|
+
|
|
211
|
+
columns.each do |column|
|
|
212
|
+
comment = column_comment(table_name, column)
|
|
213
|
+
unless comment.nil?
|
|
214
|
+
comments << "COMMENT ON COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column)} IS '#{quote_string(comment)}'"
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
join_with_statement_token(comments)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def foreign_key_definition(to_table, options = {}) # :nodoc:
|
|
222
|
+
column_sql = quote_column_name(options[:column] || "#{to_table.to_s.singularize}_id")
|
|
223
|
+
references = options[:references] ? options[:references].first : nil
|
|
224
|
+
references_sql = quote_column_name(options[:primary_key] || references || "id")
|
|
225
|
+
|
|
226
|
+
sql = "FOREIGN KEY (#{column_sql}) REFERENCES #{quote_table_name(to_table)}(#{references_sql})"
|
|
227
|
+
|
|
228
|
+
case options[:dependent]
|
|
229
|
+
when :nullify
|
|
230
|
+
sql << " ON DELETE SET NULL"
|
|
231
|
+
when :delete
|
|
232
|
+
sql << " ON DELETE CASCADE"
|
|
233
|
+
end
|
|
234
|
+
sql
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Extract all stored procedures, packages, synonyms.
|
|
238
|
+
def structure_dump_db_stored_code # :nodoc:
|
|
239
|
+
structure = []
|
|
240
|
+
all_source = select_all(<<~SQL.squish, "SCHEMA")
|
|
241
|
+
SELECT DISTINCT name, type
|
|
242
|
+
FROM all_source
|
|
243
|
+
WHERE type IN ('PROCEDURE', 'PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'TRIGGER', 'TYPE')
|
|
244
|
+
AND name NOT LIKE 'BIN$%'
|
|
245
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY type
|
|
246
|
+
SQL
|
|
247
|
+
all_source.each do |source|
|
|
248
|
+
ddl = +"CREATE OR REPLACE \n"
|
|
249
|
+
texts = select_all(<<~SQL.squish, "all source at structure dump", [bind_string("source_name", source["name"]), bind_string("source_type", source["type"])])
|
|
250
|
+
SELECT text
|
|
251
|
+
FROM all_source
|
|
252
|
+
WHERE name = :source_name
|
|
253
|
+
AND type = :source_type
|
|
254
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
255
|
+
ORDER BY line
|
|
256
|
+
SQL
|
|
257
|
+
texts.each do |row|
|
|
258
|
+
ddl << row["text"]
|
|
259
|
+
end
|
|
260
|
+
ddl << ";" unless ddl.strip[-1, 1] == ";"
|
|
261
|
+
structure << ddl
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# export synonyms
|
|
265
|
+
structure << structure_dump_synonyms
|
|
266
|
+
|
|
267
|
+
join_with_statement_token(structure)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def structure_dump_views # :nodoc:
|
|
271
|
+
structure = []
|
|
272
|
+
views = select_all(<<~SQL.squish, "SCHEMA")
|
|
273
|
+
SELECT view_name, text FROM all_views
|
|
274
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY view_name ASC
|
|
275
|
+
SQL
|
|
276
|
+
views.each do |view|
|
|
277
|
+
structure << "CREATE OR REPLACE FORCE VIEW #{view['view_name']} AS\n #{view['text']}"
|
|
278
|
+
end
|
|
279
|
+
join_with_statement_token(structure)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def structure_dump_synonyms # :nodoc:
|
|
283
|
+
structure = []
|
|
284
|
+
synonyms = select_all(<<~SQL.squish, "SCHEMA")
|
|
285
|
+
SELECT owner, synonym_name, table_name, table_owner
|
|
286
|
+
FROM all_synonyms
|
|
287
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
288
|
+
SQL
|
|
289
|
+
synonyms.each do |synonym|
|
|
290
|
+
structure << "CREATE OR REPLACE #{synonym['owner'] == 'PUBLIC' ? 'PUBLIC' : '' } SYNONYM #{synonym['synonym_name']}
|
|
291
|
+
FOR #{synonym['table_owner']}.#{synonym['table_name']}"
|
|
292
|
+
end
|
|
293
|
+
join_with_statement_token(structure)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def structure_drop # :nodoc:
|
|
297
|
+
sequences = select_values(<<~SQL.squish, "SCHEMA")
|
|
298
|
+
SELECT
|
|
299
|
+
sequence_name FROM all_sequences where sequence_owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
|
|
300
|
+
SQL
|
|
301
|
+
statements = sequences.map do |seq|
|
|
302
|
+
"DROP SEQUENCE \"#{seq}\""
|
|
303
|
+
end
|
|
304
|
+
tables = select_values(<<~SQL.squish, "SCHEMA")
|
|
305
|
+
SELECT table_name from all_tables t
|
|
306
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'
|
|
307
|
+
AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv
|
|
308
|
+
WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
|
|
309
|
+
AND NOT EXISTS (SELECT mvl.log_table FROM all_mview_logs mvl
|
|
310
|
+
WHERE mvl.log_owner = t.owner AND mvl.log_table = t.table_name)
|
|
311
|
+
ORDER BY 1
|
|
312
|
+
SQL
|
|
313
|
+
tables.each do |table|
|
|
314
|
+
statements << "DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
|
|
315
|
+
end
|
|
316
|
+
join_with_statement_token(statements)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def temp_table_drop # :nodoc:
|
|
320
|
+
temporary_tables = select_values(<<~SQL.squish, "SCHEMA")
|
|
321
|
+
SELECT table_name FROM all_tables
|
|
322
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
323
|
+
AND secondary = 'N' AND temporary = 'Y' ORDER BY 1
|
|
324
|
+
SQL
|
|
325
|
+
statements = temporary_tables.map do |table|
|
|
326
|
+
"DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
|
|
327
|
+
end
|
|
328
|
+
join_with_statement_token(statements)
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def full_drop(preserve_tables = false) # :nodoc:
|
|
332
|
+
s = preserve_tables ? [] : [structure_drop]
|
|
333
|
+
s << temp_table_drop if preserve_tables
|
|
334
|
+
s << drop_sql_for_feature("view")
|
|
335
|
+
s << drop_sql_for_feature("materialized view")
|
|
336
|
+
s << drop_sql_for_feature("synonym")
|
|
337
|
+
s << drop_sql_for_feature("type")
|
|
338
|
+
s << drop_sql_for_object("package")
|
|
339
|
+
s << drop_sql_for_object("function")
|
|
340
|
+
s << drop_sql_for_object("procedure")
|
|
341
|
+
s.join
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def execute_structure_dump(string)
|
|
345
|
+
string.split(STATEMENT_TOKEN).each do |ddl|
|
|
346
|
+
execute(ddl) unless ddl.blank?
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
private
|
|
351
|
+
# Called only if `supports_virtual_columns?` returns true
|
|
352
|
+
# return [{'column_name' => 'FOOS', 'data_default' => '...'}, ...]
|
|
353
|
+
def virtual_columns_for(table)
|
|
354
|
+
select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table.upcase)])
|
|
355
|
+
SELECT column_name, data_default
|
|
356
|
+
FROM all_tab_cols
|
|
357
|
+
WHERE virtual_column = 'YES'
|
|
358
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
359
|
+
AND table_name = :table_name
|
|
360
|
+
SQL
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def drop_sql_for_feature(type)
|
|
364
|
+
short_type = type == "materialized view" ? "mview" : type
|
|
365
|
+
features = select_values(<<~SQL.squish, "SCHEMA")
|
|
366
|
+
SELECT #{short_type}_name FROM all_#{short_type.tableize}
|
|
367
|
+
where owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
368
|
+
SQL
|
|
369
|
+
statements = features.map do |name|
|
|
370
|
+
"DROP #{type.upcase} \"#{name}\""
|
|
371
|
+
end
|
|
372
|
+
join_with_statement_token(statements)
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def drop_sql_for_object(type)
|
|
376
|
+
objects = select_values(<<~SQL.squish, "SCHEMA")
|
|
377
|
+
SELECT object_name FROM all_objects
|
|
378
|
+
WHERE object_type = '#{type.upcase}' and owner = SYS_CONTEXT('userenv', 'current_schema')
|
|
379
|
+
SQL
|
|
380
|
+
statements = objects.map do |name|
|
|
381
|
+
"DROP #{type.upcase} \"#{name}\""
|
|
382
|
+
end
|
|
383
|
+
join_with_statement_token(statements)
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def join_with_statement_token(array)
|
|
387
|
+
string = array.join(STATEMENT_TOKEN)
|
|
388
|
+
string << STATEMENT_TOKEN unless string.blank?
|
|
389
|
+
string
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module ConnectionAdapters # :nodoc:
|
|
5
|
+
module OracleEnhanced
|
|
6
|
+
class TypeMetadata < DelegateClass(ActiveRecord::ConnectionAdapters::SqlTypeMetadata) # :nodoc:
|
|
7
|
+
include Deduplicable
|
|
8
|
+
|
|
9
|
+
attr_reader :virtual
|
|
10
|
+
|
|
11
|
+
def initialize(type_metadata, virtual: nil)
|
|
12
|
+
super(type_metadata)
|
|
13
|
+
@type_metadata = type_metadata
|
|
14
|
+
@virtual = virtual
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def ==(other)
|
|
18
|
+
other.is_a?(OracleEnhanced::TypeMetadata) &&
|
|
19
|
+
attributes_for_hash == other.attributes_for_hash
|
|
20
|
+
end
|
|
21
|
+
alias eql? ==
|
|
22
|
+
|
|
23
|
+
def hash
|
|
24
|
+
attributes_for_hash.hash
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
protected
|
|
28
|
+
def attributes_for_hash
|
|
29
|
+
[self.class, @type_metadata, virtual]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|