activerecord-oracle_enhanced-adapter 1.4.3 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/History.md +1162 -2
- data/README.md +567 -155
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +3 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +19 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +132 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +345 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +52 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +280 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +64 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +59 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +538 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +38 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +46 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +435 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +44 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +196 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +164 -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 +79 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +194 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +709 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +28 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +353 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +33 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +3 -0
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +385 -1083
- data/lib/active_record/type/oracle_enhanced/boolean.rb +20 -0
- data/lib/active_record/type/oracle_enhanced/integer.rb +15 -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 +5 -13
- data/spec/active_record/connection_adapters/{oracle_enhanced_emulate_oracle_adapter_spec.rb → emulation/oracle_adapter_spec.rb} +5 -4
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +469 -0
- data/spec/active_record/connection_adapters/{oracle_enhanced_context_index_spec.rb → oracle_enhanced/context_index_spec.rb} +140 -128
- data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +112 -0
- data/spec/active_record/connection_adapters/{oracle_enhanced_dbms_output_spec.rb → oracle_enhanced/dbms_output_spec.rb} +13 -13
- data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +365 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +196 -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 +1433 -0
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +478 -0
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +385 -550
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +92 -1249
- data/spec/active_record/oracle_enhanced/type/binary_spec.rb +119 -0
- data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +208 -0
- data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +139 -0
- data/spec/active_record/oracle_enhanced/type/float_spec.rb +48 -0
- data/spec/active_record/oracle_enhanced/type/integer_spec.rb +91 -0
- data/spec/active_record/oracle_enhanced/type/json_spec.rb +57 -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 +122 -0
- data/spec/active_record/oracle_enhanced/type/text_spec.rb +229 -0
- data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +75 -0
- data/spec/spec_config.yaml.template +11 -0
- data/spec/spec_helper.rb +100 -93
- 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 +105 -152
- data/.rspec +0 -2
- data/Gemfile +0 -52
- data/RUNNING_TESTS.md +0 -45
- data/Rakefile +0 -59
- data/activerecord-oracle_enhanced-adapter.gemspec +0 -130
- data/lib/active_record/connection_adapters/oracle_enhanced.rake +0 -105
- data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +0 -41
- data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +0 -121
- data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +0 -151
- data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +0 -119
- data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +0 -359
- data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +0 -25
- data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +0 -21
- data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +0 -46
- data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +0 -572
- data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +0 -497
- data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +0 -260
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +0 -227
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +0 -260
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +0 -428
- data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +0 -258
- data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +0 -294
- data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +0 -17
- data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +0 -1
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +0 -334
- data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +0 -19
- data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +0 -141
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +0 -378
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +0 -440
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +0 -1400
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +0 -339
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module OracleEnhanced
|
6
|
+
module DatabaseLimits
|
7
|
+
# maximum length of Oracle identifiers
|
8
|
+
IDENTIFIER_MAX_LENGTH = 30
|
9
|
+
|
10
|
+
def table_alias_length #:nodoc:
|
11
|
+
IDENTIFIER_MAX_LENGTH
|
12
|
+
end
|
13
|
+
|
14
|
+
# the maximum length of a table name
|
15
|
+
def table_name_length
|
16
|
+
IDENTIFIER_MAX_LENGTH
|
17
|
+
end
|
18
|
+
|
19
|
+
# the maximum length of a column name
|
20
|
+
def column_name_length
|
21
|
+
IDENTIFIER_MAX_LENGTH
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the maximum allowed length for an index name. This
|
25
|
+
# limit is enforced by rails and Is less than or equal to
|
26
|
+
# <tt>index_name_length</tt>. The gap between
|
27
|
+
# <tt>index_name_length</tt> is to allow internal rails
|
28
|
+
# opreations to use prefixes in temporary opreations.
|
29
|
+
def allowed_index_name_length
|
30
|
+
index_name_length
|
31
|
+
end
|
32
|
+
|
33
|
+
# the maximum length of an index name
|
34
|
+
# supported by this database
|
35
|
+
def index_name_length
|
36
|
+
IDENTIFIER_MAX_LENGTH
|
37
|
+
end
|
38
|
+
|
39
|
+
# the maximum length of a sequence name
|
40
|
+
def sequence_name_length
|
41
|
+
IDENTIFIER_MAX_LENGTH
|
42
|
+
end
|
43
|
+
|
44
|
+
# To avoid ORA-01795: maximum number of expressions in a list is 1000
|
45
|
+
# tell ActiveRecord to limit us to 1000 ids at a time
|
46
|
+
def in_clause_length
|
47
|
+
1000
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,280 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module OracleEnhanced
|
6
|
+
module DatabaseStatements
|
7
|
+
# DATABASE STATEMENTS ======================================
|
8
|
+
#
|
9
|
+
# see: abstract/database_statements.rb
|
10
|
+
|
11
|
+
# Executes a SQL statement
|
12
|
+
def execute(sql, name = nil)
|
13
|
+
log(sql, name) { @connection.exec(sql) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def clear_cache!
|
17
|
+
@statements.clear
|
18
|
+
reload_type_map
|
19
|
+
end
|
20
|
+
|
21
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
22
|
+
type_casted_binds = type_casted_binds(binds)
|
23
|
+
|
24
|
+
log(sql, name, binds, type_casted_binds) do
|
25
|
+
cursor = nil
|
26
|
+
cached = false
|
27
|
+
if without_prepared_statement?(binds)
|
28
|
+
cursor = @connection.prepare(sql)
|
29
|
+
else
|
30
|
+
unless @statements.key? sql
|
31
|
+
@statements[sql] = @connection.prepare(sql)
|
32
|
+
end
|
33
|
+
|
34
|
+
cursor = @statements[sql]
|
35
|
+
|
36
|
+
cursor.bind_params(type_casted_binds)
|
37
|
+
|
38
|
+
cached = true
|
39
|
+
end
|
40
|
+
|
41
|
+
cursor.exec
|
42
|
+
|
43
|
+
if (name == "EXPLAIN") && sql =~ /^EXPLAIN/
|
44
|
+
res = true
|
45
|
+
else
|
46
|
+
columns = cursor.get_col_names.map do |col_name|
|
47
|
+
oracle_downcase(col_name)
|
48
|
+
end
|
49
|
+
rows = []
|
50
|
+
fetch_options = { get_lob_value: (name != "Writable Large Object") }
|
51
|
+
while row = cursor.fetch(fetch_options)
|
52
|
+
rows << row
|
53
|
+
end
|
54
|
+
res = ActiveRecord::Result.new(columns, rows)
|
55
|
+
end
|
56
|
+
|
57
|
+
cursor.close unless cached
|
58
|
+
res
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def supports_explain?
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
def explain(arel, binds = [])
|
67
|
+
sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
|
68
|
+
return if sql =~ /FROM all_/
|
69
|
+
if ORACLE_ENHANCED_CONNECTION == :jdbc
|
70
|
+
exec_query(sql, "EXPLAIN", binds)
|
71
|
+
else
|
72
|
+
exec_query(sql, "EXPLAIN")
|
73
|
+
end
|
74
|
+
select_values("SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)", "EXPLAIN").join("\n")
|
75
|
+
end
|
76
|
+
|
77
|
+
# New method in ActiveRecord 3.1
|
78
|
+
# Will add RETURNING clause in case of trigger generated primary keys
|
79
|
+
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
80
|
+
unless id_value || pk == false || pk.nil? || pk.is_a?(Array)
|
81
|
+
sql = "#{sql} RETURNING #{quote_column_name(pk)} INTO :returning_id"
|
82
|
+
(binds = binds.dup) << ActiveRecord::Relation::QueryAttribute.new("returning_id", nil, Type::OracleEnhanced::Integer.new)
|
83
|
+
end
|
84
|
+
super
|
85
|
+
end
|
86
|
+
|
87
|
+
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
|
88
|
+
pk = nil if id_value
|
89
|
+
super
|
90
|
+
end
|
91
|
+
|
92
|
+
# New method in ActiveRecord 3.1
|
93
|
+
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
|
94
|
+
sql, binds = sql_for_insert(sql, pk, nil, sequence_name, binds)
|
95
|
+
type_casted_binds = type_casted_binds(binds)
|
96
|
+
|
97
|
+
log(sql, name, binds, type_casted_binds) do
|
98
|
+
cached = false
|
99
|
+
returning_id_col = returning_id_index = nil
|
100
|
+
if without_prepared_statement?(binds)
|
101
|
+
cursor = @connection.prepare(sql)
|
102
|
+
else
|
103
|
+
unless @statements.key?(sql)
|
104
|
+
@statements[sql] = @connection.prepare(sql)
|
105
|
+
end
|
106
|
+
|
107
|
+
cursor = @statements[sql]
|
108
|
+
|
109
|
+
cursor.bind_params(type_casted_binds)
|
110
|
+
|
111
|
+
if sql =~ /:returning_id/
|
112
|
+
# it currently expects that returning_id comes last part of binds
|
113
|
+
returning_id_index = binds.size
|
114
|
+
cursor.bind_returning_param(returning_id_index, Integer)
|
115
|
+
end
|
116
|
+
|
117
|
+
cached = true
|
118
|
+
end
|
119
|
+
|
120
|
+
cursor.exec_update
|
121
|
+
|
122
|
+
rows = []
|
123
|
+
if returning_id_index
|
124
|
+
returning_id = cursor.get_returning_param(returning_id_index, Integer).to_i
|
125
|
+
rows << [returning_id]
|
126
|
+
end
|
127
|
+
cursor.close unless cached
|
128
|
+
ActiveRecord::Result.new(returning_id_col || [], rows)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# New method in ActiveRecord 3.1
|
133
|
+
def exec_update(sql, name = nil, binds = [])
|
134
|
+
type_casted_binds = type_casted_binds(binds)
|
135
|
+
|
136
|
+
log(sql, name, binds, type_casted_binds) do
|
137
|
+
cached = false
|
138
|
+
if without_prepared_statement?(binds)
|
139
|
+
cursor = @connection.prepare(sql)
|
140
|
+
else
|
141
|
+
if @statements.key?(sql)
|
142
|
+
cursor = @statements[sql]
|
143
|
+
else
|
144
|
+
cursor = @statements[sql] = @connection.prepare(sql)
|
145
|
+
end
|
146
|
+
|
147
|
+
cursor.bind_params(type_casted_binds)
|
148
|
+
|
149
|
+
cached = true
|
150
|
+
end
|
151
|
+
|
152
|
+
res = cursor.exec_update
|
153
|
+
cursor.close unless cached
|
154
|
+
res
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
alias :exec_delete :exec_update
|
159
|
+
|
160
|
+
def begin_db_transaction #:nodoc:
|
161
|
+
@connection.autocommit = false
|
162
|
+
end
|
163
|
+
|
164
|
+
def transaction_isolation_levels
|
165
|
+
# Oracle database supports `READ COMMITTED` and `SERIALIZABLE`
|
166
|
+
# No read uncommitted nor repeatable read supppoted
|
167
|
+
# http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10005.htm#SQLRF55422
|
168
|
+
{
|
169
|
+
read_committed: "READ COMMITTED",
|
170
|
+
serializable: "SERIALIZABLE"
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
def begin_isolated_db_transaction(isolation)
|
175
|
+
begin_db_transaction
|
176
|
+
execute "SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}"
|
177
|
+
end
|
178
|
+
|
179
|
+
def commit_db_transaction #:nodoc:
|
180
|
+
@connection.commit
|
181
|
+
ensure
|
182
|
+
@connection.autocommit = true
|
183
|
+
end
|
184
|
+
|
185
|
+
def exec_rollback_db_transaction #:nodoc:
|
186
|
+
@connection.rollback
|
187
|
+
ensure
|
188
|
+
@connection.autocommit = true
|
189
|
+
end
|
190
|
+
|
191
|
+
def create_savepoint(name = current_savepoint_name) #:nodoc:
|
192
|
+
execute("SAVEPOINT #{name}")
|
193
|
+
end
|
194
|
+
|
195
|
+
def exec_rollback_to_savepoint(name = current_savepoint_name) #:nodoc:
|
196
|
+
execute("ROLLBACK TO #{name}")
|
197
|
+
end
|
198
|
+
|
199
|
+
def release_savepoint(name = current_savepoint_name) #:nodoc:
|
200
|
+
# there is no RELEASE SAVEPOINT statement in Oracle
|
201
|
+
end
|
202
|
+
|
203
|
+
# Returns default sequence name for table.
|
204
|
+
# Will take all or first 26 characters of table name and append _seq suffix
|
205
|
+
def default_sequence_name(table_name, primary_key = nil)
|
206
|
+
table_name.to_s.gsub((/(^|\.)([\w$-]{1,#{sequence_name_length - 4}})([\w$-]*)$/), '\1\2_seq')
|
207
|
+
end
|
208
|
+
|
209
|
+
# Inserts the given fixture into the table. Overridden to properly handle lobs.
|
210
|
+
def insert_fixture(fixture, table_name) #:nodoc:
|
211
|
+
super
|
212
|
+
|
213
|
+
if ActiveRecord::Base.pluralize_table_names
|
214
|
+
klass = table_name.to_s.singularize.camelize
|
215
|
+
else
|
216
|
+
klass = table_name.to_s.camelize
|
217
|
+
end
|
218
|
+
|
219
|
+
klass = klass.constantize rescue nil
|
220
|
+
if klass.respond_to?(:ancestors) && klass.ancestors.include?(ActiveRecord::Base)
|
221
|
+
write_lobs(table_name, klass, fixture, klass.lob_columns)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# fallback to non bulk fixture insert
|
226
|
+
def insert_fixtures(fixtures, table_name)
|
227
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
228
|
+
`insert_fixtures` is deprecated and will be removed in the next version of Rails.
|
229
|
+
Consider using `insert_fixtures_set` for performance improvement.
|
230
|
+
MSG
|
231
|
+
fixtures.each do |fixture|
|
232
|
+
insert_fixture(fixture, table_name)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
237
|
+
disable_referential_integrity do
|
238
|
+
transaction(requires_new: true) do
|
239
|
+
tables_to_delete.each { |table| delete "DELETE FROM #{quote_table_name(table)}", "Fixture Delete" }
|
240
|
+
|
241
|
+
fixture_set.each do |table_name, rows|
|
242
|
+
rows.each { |row| insert_fixture(row, table_name) }
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
# Oracle Database does not support this feature
|
249
|
+
# Refer https://community.oracle.com/ideas/13845 and consider to vote
|
250
|
+
# if you need this feature.
|
251
|
+
def empty_insert_statement_value
|
252
|
+
raise NotImplementedError
|
253
|
+
end
|
254
|
+
|
255
|
+
# Writes LOB values from attributes for specified columns
|
256
|
+
def write_lobs(table_name, klass, attributes, columns) #:nodoc:
|
257
|
+
id = quote(attributes[klass.primary_key])
|
258
|
+
columns.each do |col|
|
259
|
+
value = attributes[col.name]
|
260
|
+
# changed sequence of next two lines - should check if value is nil before converting to yaml
|
261
|
+
next if value.blank?
|
262
|
+
if klass.attribute_types[col.name].is_a? Type::Serialized
|
263
|
+
value = klass.attribute_types[col.name].serialize(value)
|
264
|
+
end
|
265
|
+
uncached do
|
266
|
+
unless lob_record = select_one(<<-SQL.strip.gsub(/\s+/, " "), "Writable Large Object")
|
267
|
+
SELECT #{quote_column_name(col.name)} FROM #{quote_table_name(table_name)}
|
268
|
+
WHERE #{quote_column_name(klass.primary_key)} = #{id} FOR UPDATE
|
269
|
+
SQL
|
270
|
+
raise ActiveRecord::RecordNotFound, "statement #{sql} returned no rows"
|
271
|
+
end
|
272
|
+
lob = lob_record[col.name]
|
273
|
+
@connection.write_lob(lob, value.to_s, col.type == :binary)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/base"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module ConnectionAdapters
|
7
|
+
class OracleEnhancedAdapter
|
8
|
+
class DatabaseTasks
|
9
|
+
delegate :connection, :establish_connection, to: ActiveRecord::Base
|
10
|
+
|
11
|
+
def initialize(config)
|
12
|
+
@config = config
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
system_password = ENV.fetch("ORACLE_SYSTEM_PASSWORD") {
|
17
|
+
print "Please provide the SYSTEM password for your Oracle installation (set ORACLE_SYSTEM_PASSWORD to avoid this prompt)\n>"
|
18
|
+
$stdin.gets.strip
|
19
|
+
}
|
20
|
+
establish_connection(@config.merge("username" => "SYSTEM", "password" => system_password))
|
21
|
+
begin
|
22
|
+
connection.execute "CREATE USER #{@config['username']} IDENTIFIED BY #{@config['password']}"
|
23
|
+
rescue => e
|
24
|
+
if e.message =~ /ORA-01920/ # user name conflicts with another user or role name
|
25
|
+
connection.execute "ALTER USER #{@config['username']} IDENTIFIED BY #{@config['password']}"
|
26
|
+
else
|
27
|
+
raise e
|
28
|
+
end
|
29
|
+
end
|
30
|
+
connection.execute "GRANT unlimited tablespace TO #{@config['username']}"
|
31
|
+
connection.execute "GRANT create session TO #{@config['username']}"
|
32
|
+
connection.execute "GRANT create table TO #{@config['username']}"
|
33
|
+
connection.execute "GRANT create view TO #{@config['username']}"
|
34
|
+
connection.execute "GRANT create sequence TO #{@config['username']}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def drop
|
38
|
+
establish_connection(@config)
|
39
|
+
connection.execute_structure_dump(connection.full_drop)
|
40
|
+
end
|
41
|
+
|
42
|
+
def purge
|
43
|
+
drop
|
44
|
+
connection.execute("PURGE RECYCLEBIN") rescue nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def structure_dump(filename, extra_flags)
|
48
|
+
establish_connection(@config)
|
49
|
+
File.open(filename, "w:utf-8") { |f| f << connection.structure_dump }
|
50
|
+
if @config["structure_dump"] == "db_stored_code"
|
51
|
+
File.open(filename, "a") { |f| f << connection.structure_dump_db_stored_code }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def structure_load(filename, extra_flags)
|
56
|
+
establish_connection(@config)
|
57
|
+
connection.execute_structure_dump(File.read(filename))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
ActiveRecord::Tasks::DatabaseTasks.register_task(/(oci|oracle)/, ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter::DatabaseTasks)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module OracleEnhanced
|
6
|
+
module DbmsOutput
|
7
|
+
# DBMS_OUTPUT =============================================
|
8
|
+
#
|
9
|
+
# PL/SQL in Oracle uses dbms_output for logging print statements
|
10
|
+
# These methods stick that output into the Rails log so Ruby and PL/SQL
|
11
|
+
# code can can be debugged together in a single application
|
12
|
+
|
13
|
+
# Maximum DBMS_OUTPUT buffer size
|
14
|
+
DBMS_OUTPUT_BUFFER_SIZE = 10000 # can be 1-1000000
|
15
|
+
|
16
|
+
# Turn DBMS_Output logging on
|
17
|
+
def enable_dbms_output
|
18
|
+
set_dbms_output_plsql_connection
|
19
|
+
@enable_dbms_output = true
|
20
|
+
plsql(:dbms_output).sys.dbms_output.enable(DBMS_OUTPUT_BUFFER_SIZE)
|
21
|
+
end
|
22
|
+
# Turn DBMS_Output logging off
|
23
|
+
def disable_dbms_output
|
24
|
+
set_dbms_output_plsql_connection
|
25
|
+
@enable_dbms_output = false
|
26
|
+
plsql(:dbms_output).sys.dbms_output.disable
|
27
|
+
end
|
28
|
+
# Is DBMS_Output logging enabled?
|
29
|
+
def dbms_output_enabled?
|
30
|
+
@enable_dbms_output
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil)
|
36
|
+
super
|
37
|
+
ensure
|
38
|
+
log_dbms_output if dbms_output_enabled?
|
39
|
+
end
|
40
|
+
|
41
|
+
def set_dbms_output_plsql_connection
|
42
|
+
raise OracleEnhanced::ConnectionException, "ruby-plsql gem is required for logging DBMS output" unless self.respond_to?(:plsql)
|
43
|
+
# do not reset plsql connection if it is the same (as resetting will clear PL/SQL metadata cache)
|
44
|
+
unless plsql(:dbms_output).connection && plsql(:dbms_output).connection.raw_connection == raw_connection
|
45
|
+
plsql(:dbms_output).connection = raw_connection
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def log_dbms_output
|
50
|
+
while true do
|
51
|
+
result = plsql(:dbms_output).sys.dbms_output.get_line(line: "", status: 0)
|
52
|
+
break unless result[:status] == 0
|
53
|
+
@logger.debug "DBMS_OUTPUT: #{result[:line]}" if @logger
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|