activerecord-jdbc-adapter 5.0.pre1 → 50.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord-jdbc-adapter might be problematic. Click here for more details.

Files changed (66) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -2
  3. data/.travis.yml +15 -416
  4. data/Gemfile +35 -37
  5. data/README.md +23 -118
  6. data/RUNNING_TESTS.md +31 -26
  7. data/Rakefile +2 -3
  8. data/lib/arjdbc/abstract/connection_management.rb +21 -0
  9. data/lib/arjdbc/abstract/core.rb +62 -0
  10. data/lib/arjdbc/abstract/database_statements.rb +46 -0
  11. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  12. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  13. data/lib/arjdbc/derby/adapter.rb +6 -1
  14. data/lib/arjdbc/discover.rb +0 -7
  15. data/lib/arjdbc/firebird/adapter.rb +2 -2
  16. data/lib/arjdbc/jdbc.rb +2 -2
  17. data/lib/arjdbc/jdbc/adapter.rb +10 -252
  18. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  19. data/lib/arjdbc/jdbc/connection.rb +6 -0
  20. data/lib/arjdbc/mysql/adapter.rb +82 -946
  21. data/lib/arjdbc/mysql/connection_methods.rb +4 -2
  22. data/lib/arjdbc/postgresql/adapter.rb +270 -970
  23. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  24. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  25. data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
  26. data/lib/arjdbc/postgresql/column.rb +10 -599
  27. data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
  28. data/lib/arjdbc/postgresql/name.rb +24 -0
  29. data/lib/arjdbc/postgresql/oid_types.rb +28 -109
  30. data/lib/arjdbc/sqlite3/adapter.rb +18 -42
  31. data/lib/arjdbc/tasks/database_tasks.rb +1 -3
  32. data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
  33. data/lib/arjdbc/version.rb +1 -1
  34. data/pom.xml +3 -3
  35. data/rakelib/02-test.rake +0 -12
  36. data/rakelib/compile.rake +1 -1
  37. data/rakelib/db.rake +7 -5
  38. data/rakelib/rails.rake +67 -64
  39. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
  40. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
  41. data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
  42. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
  43. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
  44. data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
  45. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
  46. metadata +16 -29
  47. data/Appraisals +0 -41
  48. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
  49. data/lib/arjdbc/common_jdbc_methods.rb +0 -89
  50. data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
  51. data/lib/arjdbc/mysql/column.rb +0 -162
  52. data/lib/arjdbc/mysql/explain_support.rb +0 -82
  53. data/lib/arjdbc/mysql/schema_creation.rb +0 -58
  54. data/lib/arjdbc/oracle.rb +0 -4
  55. data/lib/arjdbc/oracle/adapter.rb +0 -952
  56. data/lib/arjdbc/oracle/column.rb +0 -126
  57. data/lib/arjdbc/oracle/connection_methods.rb +0 -21
  58. data/lib/arjdbc/postgresql/base/oid.rb +0 -412
  59. data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
  60. data/lib/arjdbc/postgresql/explain_support.rb +0 -53
  61. data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
  62. data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
  63. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
  64. data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
  65. data/src/java/arjdbc/oracle/OracleModule.java +0 -75
  66. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +0 -465
@@ -1,131 +0,0 @@
1
- module ActiveRecord
2
- module ConnectionAdapters
3
- module PostgreSQL
4
- class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
5
- attr_accessor :array
6
- def array?; !!@array; end
7
- end
8
-
9
- module ColumnMethods
10
- def xml(*args)
11
- options = args.extract_options!
12
- column(args[0], 'xml', options)
13
- end
14
-
15
- def tsvector(*args)
16
- options = args.extract_options!
17
- column(args[0], 'tsvector', options)
18
- end
19
-
20
- def int4range(name, options = {})
21
- column(name, 'int4range', options)
22
- end
23
-
24
- def int8range(name, options = {})
25
- column(name, 'int8range', options)
26
- end
27
-
28
- def tsrange(name, options = {})
29
- column(name, 'tsrange', options)
30
- end
31
-
32
- def tstzrange(name, options = {})
33
- column(name, 'tstzrange', options)
34
- end
35
-
36
- def numrange(name, options = {})
37
- column(name, 'numrange', options)
38
- end
39
-
40
- def daterange(name, options = {})
41
- column(name, 'daterange', options)
42
- end
43
-
44
- def hstore(name, options = {})
45
- column(name, 'hstore', options)
46
- end
47
-
48
- def ltree(name, options = {})
49
- column(name, 'ltree', options)
50
- end
51
-
52
- def inet(name, options = {})
53
- column(name, 'inet', options)
54
- end
55
-
56
- def cidr(name, options = {})
57
- column(name, 'cidr', options)
58
- end
59
-
60
- def macaddr(name, options = {})
61
- column(name, 'macaddr', options)
62
- end
63
-
64
- def uuid(name, options = {})
65
- column(name, 'uuid', options)
66
- end
67
-
68
- def json(name, options = {})
69
- column(name, 'json', options)
70
- end
71
-
72
- def jsonb(name, options = {})
73
- column(name, :jsonb, options)
74
- end
75
-
76
- def bit(name, options)
77
- column(name, 'bit', options)
78
- end
79
-
80
- def bit_varying(name, options)
81
- column(name, 'bit varying', options)
82
- end
83
- end
84
-
85
- class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
86
- include ColumnMethods
87
-
88
- def primary_key(name, type = :primary_key, options = {})
89
- return super unless type == :uuid
90
- options[:default] = options.fetch(:default, 'uuid_generate_v4()')
91
- options[:primary_key] = true
92
- column name, type, options
93
- end if ::ActiveRecord::VERSION::MAJOR > 3 # 3.2 super expects (name)
94
-
95
- def column(name, type = nil, options = {})
96
- super
97
- column = self[name]
98
- # NOTE: <= 3.1 no #new_column_definition hard-coded ColumnDef.new :
99
- # column = self[name] || ColumnDefinition.new(@base, name, type)
100
- # thus we simply do not support array column definitions on <= 3.1
101
- column.array = options[:array] if column.is_a?(ColumnDefinition)
102
- self
103
- end
104
-
105
- private
106
-
107
- if ::ActiveRecord::VERSION::MAJOR > 3
108
-
109
- def create_column_definition(name, type)
110
- ColumnDefinition.new name, type
111
- end
112
-
113
- else # no #create_column_definition on 3.2
114
-
115
- def new_column_definition(base, name, type)
116
- definition = ColumnDefinition.new base, name, type
117
- @columns << definition
118
- @columns_hash[name] = definition
119
- definition
120
- end
121
-
122
- end
123
-
124
- end
125
-
126
- class Table < ActiveRecord::ConnectionAdapters::Table
127
- include ColumnMethods
128
- end
129
- end
130
- end
131
- end
@@ -1,53 +0,0 @@
1
- module ArJdbc
2
- module PostgreSQL
3
- # @private
4
- module ExplainSupport
5
- def supports_explain?
6
- true
7
- end
8
-
9
- def explain(arel, binds = [])
10
- sql = "EXPLAIN #{to_sql(arel, binds)}"
11
- result = exec_query(sql, "EXPLAIN", binds)
12
- ExplainPrettyPrinter.new.pp result # we can assume AR >= 3.1
13
- end
14
- # @private
15
- class ExplainPrettyPrinter
16
- # Pretty prints the result of a EXPLAIN in a way that resembles the output of the
17
- # PostgreSQL shell:
18
- #
19
- # QUERY PLAN
20
- # ------------------------------------------------------------------------------
21
- # Nested Loop Left Join (cost=0.00..37.24 rows=8 width=0)
22
- # Join Filter: (posts.user_id = users.id)
23
- # -> Index Scan using users_pkey on users (cost=0.00..8.27 rows=1 width=4)
24
- # Index Cond: (id = 1)
25
- # -> Seq Scan on posts (cost=0.00..28.88 rows=8 width=4)
26
- # Filter: (posts.user_id = 1)
27
- # (6 rows)
28
- #
29
- def pp(result)
30
- header = result.columns.first
31
- lines = result.rows.map(&:first)
32
-
33
- # We add 2 because there's one char of padding at both sides, note
34
- # the extra hyphens in the example above.
35
- width = [header, *lines].map(&:length).max + 2
36
-
37
- pp = []
38
-
39
- pp << header.center(width).rstrip
40
- pp << '-' * width
41
-
42
- pp += lines.map {|line| " #{line}"}
43
-
44
- nrows = result.rows.length
45
- rows_label = nrows == 1 ? 'row' : 'rows'
46
- pp << "(#{nrows} #{rows_label})"
47
-
48
- pp.join("\n") + "\n"
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,2 +0,0 @@
1
- class ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Bytea
2
- end
@@ -1,60 +0,0 @@
1
- module ArJdbc
2
- module PostgreSQL
3
- # @private copied (and adjusted) from native adapter 4.0/4.1/4.2
4
- class SchemaCreation < ::ActiveRecord::ConnectionAdapters::AbstractAdapter::SchemaCreation
5
-
6
- private
7
-
8
- def visit_AddColumn(o)
9
- sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
10
- sql = "ADD COLUMN #{quote_column_name(o.name)} #{sql_type}"
11
- add_column_options!(sql, column_options(o))
12
- end unless AR42
13
-
14
- def visit_ColumnDefinition(o)
15
- sql = super
16
- if o.primary_key? && o.type == :uuid
17
- sql << " PRIMARY KEY "
18
- add_column_options!(sql, column_options(o))
19
- end
20
- sql
21
- end unless AR42
22
-
23
- def visit_ColumnDefinition(o)
24
- sql = super
25
- if o.primary_key? && o.type != :primary_key
26
- sql << " PRIMARY KEY "
27
- add_column_options!(sql, column_options(o))
28
- end
29
- sql
30
- end if AR42
31
-
32
- def add_column_options!(sql, options)
33
- if options[:array] || options[:column].try(:array)
34
- sql << '[]'
35
- end
36
-
37
- column = options.fetch(:column) { return super }
38
- if column.type == :uuid && options[:default] =~ /\(\)/
39
- sql << " DEFAULT #{options[:default]}"
40
- else
41
- super
42
- end
43
- end
44
-
45
- def type_for_column(column)
46
- if column.array
47
- @conn.lookup_cast_type("#{column.sql_type}[]")
48
- else
49
- super
50
- end
51
- end if AR42
52
-
53
- end
54
-
55
- def schema_creation
56
- SchemaCreation.new self
57
- end
58
-
59
- end
60
- end if ::ActiveRecord::ConnectionAdapters::AbstractAdapter.const_defined? :SchemaCreation
@@ -1,297 +0,0 @@
1
- # NOTE: kindly copy-pasted from Raimonds Simanovskis's oracle-enhanced adapter :
2
- # https://github.com/rsim/oracle-enhanced/blob/master/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb
3
-
4
- module ActiveRecord #:nodoc:
5
- module ConnectionAdapters #:nodoc:
6
- module OracleEnhancedStructureDump #:nodoc:
7
-
8
- # Statements separator used in structure dump to allow loading of structure dump also with SQL*Plus
9
- STATEMENT_TOKEN = "\n\n/\n\n"
10
-
11
- def structure_dump #:nodoc:
12
- structure = select_values("SELECT sequence_name FROM user_sequences ORDER BY 1").map do |seq|
13
- "CREATE SEQUENCE \"#{seq}\""
14
- end
15
- select_values("SELECT table_name FROM all_tables t
16
- WHERE owner = SYS_CONTEXT('userenv', 'session_user') AND secondary = 'N'
17
- AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
18
- AND NOT EXISTS (SELECT mvl.log_table FROM all_mview_logs mvl WHERE mvl.log_owner = t.owner AND mvl.log_table = t.table_name)
19
- ORDER BY 1").each do |table_name|
20
- virtual_columns = virtual_columns_for(table_name)
21
- ddl = "CREATE#{ ' GLOBAL TEMPORARY' if temporary_table?(table_name)} TABLE \"#{table_name}\" (\n"
22
- cols = select_all(%Q{
23
- SELECT column_name, data_type, data_length, char_used, char_length, data_precision, data_scale, data_default, nullable
24
- FROM user_tab_columns
25
- WHERE table_name = '#{table_name}'
26
- ORDER BY column_id
27
- }).map do |row|
28
- if(v = virtual_columns.find {|col| col['column_name'] == row['column_name']})
29
- structure_dump_virtual_column(row, v['data_default'])
30
- else
31
- structure_dump_column(row)
32
- end
33
- end
34
- ddl << cols.join(",\n ")
35
- ddl << structure_dump_primary_key(table_name)
36
- ddl << "\n)"
37
- structure << ddl
38
- structure << structure_dump_indexes(table_name)
39
- structure << structure_dump_unique_keys(table_name)
40
- end
41
-
42
- join_with_statement_token(structure) << structure_dump_fk_constraints
43
- end
44
-
45
- def structure_dump_column(column) #:nodoc:
46
- col = "\"#{column['column_name']}\" #{column['data_type']}"
47
- if column['data_type'] =='NUMBER' && ! column['data_precision'].blank?
48
- col << "(#{column['data_precision'].to_i}"
49
- col << ",#{column['data_scale'].to_i}" unless column['data_scale'].blank?
50
- col << ')'
51
- elsif column['data_type'].include?('CHAR')
52
- length = column['char_used'] == 'C' ? column['char_length'].to_i : column['data_length'].to_i
53
- col << "(#{length})"
54
- end
55
- col << " DEFAULT #{column['data_default']}" unless column['data_default'].blank?
56
- col << ' NOT NULL' if column['nullable'] == 'N'
57
- col
58
- end
59
-
60
- def structure_dump_virtual_column(column, data_default) #:nodoc:
61
- data_default = data_default.gsub(/"/, '')
62
- col = "\"#{column['column_name']}\" #{column['data_type']}"
63
- if column['data_type'] =='NUMBER' && ! column['data_precision'].blank?
64
- col << "(#{column['data_precision'].to_i}"
65
- col << ",#{column['data_scale'].to_i}" unless column['data_scale'].blank?
66
- col << ')'
67
- elsif column['data_type'].include?('CHAR')
68
- length = column['char_used'] == 'C' ? column['char_length'].to_i : column['data_length'].to_i
69
- col << "(#{length})"
70
- end
71
- col << " GENERATED ALWAYS AS (#{data_default}) VIRTUAL"
72
- end
73
-
74
- def structure_dump_primary_key(table) #:nodoc:
75
- opts = {:name => '', :cols => []}
76
- pks = select_all(<<-SQL, "Primary Keys")
77
- SELECT a.constraint_name, a.column_name, a.position
78
- FROM user_cons_columns a
79
- JOIN user_constraints c
80
- ON a.constraint_name = c.constraint_name
81
- WHERE c.table_name = '#{table.upcase}'
82
- AND c.constraint_type = 'P'
83
- AND c.owner = SYS_CONTEXT('userenv', 'session_user')
84
- SQL
85
- pks.each do |row|
86
- opts[:name] = row['constraint_name']
87
- opts[:cols][row['position']-1] = row['column_name']
88
- end
89
- opts[:cols].length > 0 ? ",\n CONSTRAINT #{opts[:name]} PRIMARY KEY (#{opts[:cols].join(',')})" : ''
90
- end
91
-
92
- def structure_dump_unique_keys(table) #:nodoc:
93
- keys = {}
94
- uks = select_all(<<-SQL, "Primary Keys")
95
- SELECT a.constraint_name, a.column_name, a.position
96
- FROM user_cons_columns a
97
- JOIN user_constraints c
98
- ON a.constraint_name = c.constraint_name
99
- WHERE c.table_name = '#{table.upcase}'
100
- AND c.constraint_type = 'U'
101
- AND c.owner = SYS_CONTEXT('userenv', 'session_user')
102
- SQL
103
- uks.each do |uk|
104
- keys[uk['constraint_name']] ||= []
105
- keys[uk['constraint_name']][uk['position']-1] = uk['column_name']
106
- end
107
- keys.map do |k,v|
108
- "ALTER TABLE #{table.upcase} ADD CONSTRAINT #{k} UNIQUE (#{v.join(',')})"
109
- end
110
- end
111
-
112
- def structure_dump_indexes(table_name) #:nodoc:
113
- indexes(table_name).map do |options|
114
- column_names = options[:columns]
115
- options = {:name => options[:name], :unique => options[:unique]}
116
- index_name = index_name(table_name, :column => column_names)
117
- if Hash === options # legacy support, since this param was a string
118
- index_type = options[:unique] ? "UNIQUE" : ""
119
- index_name = options[:name] || index_name
120
- else
121
- index_type = options
122
- end
123
- quoted_column_names = column_names.map { |e| quote_column_name_or_expression(e) }.join(", ")
124
- "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})"
125
- end
126
- end
127
-
128
- def structure_dump_fk_constraints #:nodoc:
129
- fks = select_all("SELECT table_name FROM all_tables WHERE owner = SYS_CONTEXT('userenv', 'session_user') ORDER BY 1").map do |table|
130
- if respond_to?(:foreign_keys) && (foreign_keys = foreign_keys(table["table_name"])).any?
131
- foreign_keys.map do |fk|
132
- sql = "ALTER TABLE #{quote_table_name(fk.from_table)} ADD CONSTRAINT #{quote_column_name(fk.options[:name])} "
133
- sql << "#{foreign_key_definition(fk.to_table, fk.options)}"
134
- end
135
- end
136
- end.flatten.compact
137
- join_with_statement_token(fks)
138
- end
139
-
140
- def dump_schema_information #:nodoc:
141
- sm_table = ActiveRecord::Migrator.schema_migrations_table_name
142
- migrated = select_values("SELECT version FROM #{sm_table} ORDER BY version")
143
- join_with_statement_token(migrated.map{|v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}')" })
144
- end
145
-
146
- # Extract all stored procedures, packages, synonyms and views.
147
- def structure_dump_db_stored_code #:nodoc:
148
- structure = []
149
- select_all("SELECT DISTINCT name, type
150
- FROM all_source
151
- WHERE type IN ('PROCEDURE', 'PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'TRIGGER', 'TYPE')
152
- AND name NOT LIKE 'BIN$%'
153
- AND owner = SYS_CONTEXT('userenv', 'session_user') ORDER BY type").each do |source|
154
- ddl = "CREATE OR REPLACE \n"
155
- select_all(%Q{
156
- SELECT text
157
- FROM all_source
158
- WHERE name = '#{source['name']}'
159
- AND type = '#{source['type']}'
160
- AND owner = SYS_CONTEXT('userenv', 'session_user')
161
- ORDER BY line
162
- }).each do |row|
163
- ddl << row['text']
164
- end
165
- ddl << ";" unless ddl.strip[-1,1] == ';'
166
- structure << ddl
167
- end
168
-
169
- # export views
170
- select_all("SELECT view_name, text FROM user_views").each do |view|
171
- structure << "CREATE OR REPLACE VIEW #{view['view_name']} AS\n #{view['text']}"
172
- end
173
-
174
- # export synonyms
175
- select_all("SELECT owner, synonym_name, table_name, table_owner
176
- FROM all_synonyms
177
- WHERE owner = SYS_CONTEXT('userenv', 'session_user') ").each do |synonym|
178
- structure << "CREATE OR REPLACE #{synonym['owner'] == 'PUBLIC' ? 'PUBLIC' : '' } SYNONYM #{synonym['synonym_name']}"
179
- structure << " FOR #{synonym['table_owner']}.#{synonym['table_name']}"
180
- end
181
-
182
- join_with_statement_token(structure)
183
- end
184
-
185
- def structure_drop #:nodoc:
186
- statements = select_values("SELECT sequence_name FROM user_sequences ORDER BY 1").map do |seq|
187
- "DROP SEQUENCE \"#{seq}\""
188
- end
189
- select_values("SELECT table_name from all_tables t
190
- WHERE owner = SYS_CONTEXT('userenv', 'session_user') AND secondary = 'N'
191
- AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
192
- AND NOT EXISTS (SELECT mvl.log_table FROM all_mview_logs mvl WHERE mvl.log_owner = t.owner AND mvl.log_table = t.table_name)
193
- ORDER BY 1").each do |table|
194
- statements << "DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
195
- end
196
- join_with_statement_token(statements)
197
- end
198
-
199
- def temp_table_drop #:nodoc:
200
- join_with_statement_token(select_values(
201
- "SELECT table_name FROM all_tables
202
- WHERE owner = SYS_CONTEXT('userenv', 'session_user') AND secondary = 'N' AND temporary = 'Y' ORDER BY 1").map do |table|
203
- "DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
204
- end)
205
- end
206
-
207
- def full_drop(preserve_tables=false) #:nodoc:
208
- s = preserve_tables ? [] : [structure_drop]
209
- s << temp_table_drop if preserve_tables
210
- s << drop_sql_for_feature("view")
211
- s << drop_sql_for_feature("materialized view")
212
- s << drop_sql_for_feature("synonym")
213
- s << drop_sql_for_feature("type")
214
- s << drop_sql_for_object("package")
215
- s << drop_sql_for_object("function")
216
- s << drop_sql_for_object("procedure")
217
- s.join
218
- end
219
-
220
- def add_column_options!(sql, options) #:nodoc:
221
- type = options[:type] || ((column = options[:column]) && column.type)
222
- type = type && type.to_sym
223
- # handle case of defaults for CLOB columns, which would otherwise get "quoted" incorrectly
224
- if options_include_default?(options)
225
- if type == :text
226
- sql << " DEFAULT #{quote(options[:default])}"
227
- else
228
- # from abstract adapter
229
- sql << " DEFAULT #{quote(options[:default], options[:column])}"
230
- end
231
- end
232
- # must explicitly add NULL or NOT NULL to allow change_column to work on migrations
233
- if options[:null] == false
234
- sql << " NOT NULL"
235
- elsif options[:null] == true
236
- sql << " NULL" unless type == :primary_key
237
- end
238
- # add AS expression for virtual columns
239
- if options[:as].present?
240
- sql << " AS (#{options[:as]})"
241
- end
242
- end
243
-
244
- def execute_structure_dump(string)
245
- string.split(STATEMENT_TOKEN).each do |ddl|
246
- ddl.chop! if ddl[-1,1] == ';'
247
- execute(ddl) unless ddl.blank?
248
- end
249
- end
250
-
251
- private
252
-
253
- # virtual columns are an 11g feature. This returns [] if feature is not
254
- # present or none are found.
255
- # return [{'column_name' => 'FOOS', 'data_default' => '...'}, ...]
256
- def virtual_columns_for(table)
257
- begin
258
- select_all <<-SQL
259
- SELECT column_name, data_default
260
- FROM user_tab_cols
261
- WHERE virtual_column = 'YES'
262
- AND table_name = '#{table.upcase}'
263
- SQL
264
- # feature not supported previous to 11g
265
- rescue ActiveRecord::StatementInvalid => e
266
- []
267
- end
268
- end
269
-
270
- def drop_sql_for_feature(type)
271
- short_type = type == 'materialized view' ? 'mview' : type
272
- join_with_statement_token(
273
- select_values("SELECT #{short_type}_name FROM user_#{short_type.tableize}").map do |name|
274
- "DROP #{type.upcase} \"#{name}\""
275
- end)
276
- end
277
-
278
- def drop_sql_for_object(type)
279
- join_with_statement_token(
280
- select_values("SELECT object_name FROM user_objects WHERE object_type = '#{type.upcase}'").map do |name|
281
- "DROP #{type.upcase} \"#{name}\""
282
- end)
283
- end
284
-
285
- def join_with_statement_token(array)
286
- string = array.join(STATEMENT_TOKEN)
287
- string << STATEMENT_TOKEN unless string.blank?
288
- string
289
- end
290
-
291
- end
292
- end
293
- end
294
-
295
- ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
296
- include ActiveRecord::ConnectionAdapters::OracleEnhancedStructureDump
297
- end