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.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +1162 -2
  3. data/README.md +567 -155
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +3 -1
  6. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +19 -0
  7. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +132 -0
  8. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +345 -0
  9. data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +52 -0
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +280 -0
  11. data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +64 -0
  12. data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +59 -0
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +538 -0
  14. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +38 -0
  15. data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +46 -0
  16. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +435 -0
  17. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +44 -0
  18. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +196 -0
  19. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +164 -0
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +95 -0
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +79 -0
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +194 -0
  23. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +709 -0
  24. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +28 -0
  25. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +353 -0
  26. data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +33 -0
  27. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +3 -0
  28. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +385 -1083
  29. data/lib/active_record/type/oracle_enhanced/boolean.rb +20 -0
  30. data/lib/active_record/type/oracle_enhanced/integer.rb +15 -0
  31. data/lib/active_record/type/oracle_enhanced/json.rb +10 -0
  32. data/lib/active_record/type/oracle_enhanced/national_character_string.rb +26 -0
  33. data/lib/active_record/type/oracle_enhanced/national_character_text.rb +36 -0
  34. data/lib/active_record/type/oracle_enhanced/raw.rb +25 -0
  35. data/lib/active_record/type/oracle_enhanced/string.rb +29 -0
  36. data/lib/active_record/type/oracle_enhanced/text.rb +32 -0
  37. data/lib/active_record/type/oracle_enhanced/timestampltz.rb +25 -0
  38. data/lib/active_record/type/oracle_enhanced/timestamptz.rb +25 -0
  39. data/lib/activerecord-oracle_enhanced-adapter.rb +5 -13
  40. data/spec/active_record/connection_adapters/{oracle_enhanced_emulate_oracle_adapter_spec.rb → emulation/oracle_adapter_spec.rb} +5 -4
  41. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +469 -0
  42. data/spec/active_record/connection_adapters/{oracle_enhanced_context_index_spec.rb → oracle_enhanced/context_index_spec.rb} +140 -128
  43. data/spec/active_record/connection_adapters/oracle_enhanced/database_tasks_spec.rb +112 -0
  44. data/spec/active_record/connection_adapters/{oracle_enhanced_dbms_output_spec.rb → oracle_enhanced/dbms_output_spec.rb} +13 -13
  45. data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +365 -0
  46. data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +196 -0
  47. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +492 -0
  48. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +1433 -0
  49. data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +478 -0
  50. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +385 -550
  51. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +92 -1249
  52. data/spec/active_record/oracle_enhanced/type/binary_spec.rb +119 -0
  53. data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +208 -0
  54. data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +139 -0
  55. data/spec/active_record/oracle_enhanced/type/float_spec.rb +48 -0
  56. data/spec/active_record/oracle_enhanced/type/integer_spec.rb +91 -0
  57. data/spec/active_record/oracle_enhanced/type/json_spec.rb +57 -0
  58. data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +55 -0
  59. data/spec/active_record/oracle_enhanced/type/national_character_text_spec.rb +230 -0
  60. data/spec/active_record/oracle_enhanced/type/raw_spec.rb +122 -0
  61. data/spec/active_record/oracle_enhanced/type/text_spec.rb +229 -0
  62. data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +75 -0
  63. data/spec/spec_config.yaml.template +11 -0
  64. data/spec/spec_helper.rb +100 -93
  65. data/spec/support/alter_system_set_open_cursors.sql +1 -0
  66. data/spec/support/alter_system_user_password.sql +2 -0
  67. data/spec/support/create_oracle_enhanced_users.sql +31 -0
  68. metadata +105 -152
  69. data/.rspec +0 -2
  70. data/Gemfile +0 -52
  71. data/RUNNING_TESTS.md +0 -45
  72. data/Rakefile +0 -59
  73. data/activerecord-oracle_enhanced-adapter.gemspec +0 -130
  74. data/lib/active_record/connection_adapters/oracle_enhanced.rake +0 -105
  75. data/lib/active_record/connection_adapters/oracle_enhanced_activerecord_patches.rb +0 -41
  76. data/lib/active_record/connection_adapters/oracle_enhanced_base_ext.rb +0 -121
  77. data/lib/active_record/connection_adapters/oracle_enhanced_column.rb +0 -151
  78. data/lib/active_record/connection_adapters/oracle_enhanced_connection.rb +0 -119
  79. data/lib/active_record/connection_adapters/oracle_enhanced_context_index.rb +0 -359
  80. data/lib/active_record/connection_adapters/oracle_enhanced_core_ext.rb +0 -25
  81. data/lib/active_record/connection_adapters/oracle_enhanced_cpk.rb +0 -21
  82. data/lib/active_record/connection_adapters/oracle_enhanced_dirty.rb +0 -46
  83. data/lib/active_record/connection_adapters/oracle_enhanced_jdbc_connection.rb +0 -572
  84. data/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb +0 -497
  85. data/lib/active_record/connection_adapters/oracle_enhanced_procedures.rb +0 -260
  86. data/lib/active_record/connection_adapters/oracle_enhanced_schema_definitions.rb +0 -227
  87. data/lib/active_record/connection_adapters/oracle_enhanced_schema_dumper.rb +0 -260
  88. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements.rb +0 -428
  89. data/lib/active_record/connection_adapters/oracle_enhanced_schema_statements_ext.rb +0 -258
  90. data/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb +0 -294
  91. data/lib/active_record/connection_adapters/oracle_enhanced_tasks.rb +0 -17
  92. data/lib/active_record/connection_adapters/oracle_enhanced_version.rb +0 -1
  93. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +0 -334
  94. data/spec/active_record/connection_adapters/oracle_enhanced_core_ext_spec.rb +0 -19
  95. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
  96. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +0 -141
  97. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +0 -378
  98. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +0 -440
  99. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +0 -1400
  100. 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