activerecord-jdbc-adapter 5.0.pre1 → 51.0

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.
Files changed (68) 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/activerecord-jdbc-adapter.gemspec +1 -2
  9. data/lib/arjdbc/abstract/connection_management.rb +21 -0
  10. data/lib/arjdbc/abstract/core.rb +62 -0
  11. data/lib/arjdbc/abstract/database_statements.rb +46 -0
  12. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  13. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  14. data/lib/arjdbc/derby/adapter.rb +6 -1
  15. data/lib/arjdbc/discover.rb +0 -7
  16. data/lib/arjdbc/firebird/adapter.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/jdbc.rb +2 -2
  21. data/lib/arjdbc/mysql/adapter.rb +87 -944
  22. data/lib/arjdbc/mysql/connection_methods.rb +4 -2
  23. data/lib/arjdbc/postgresql/adapter.rb +288 -1023
  24. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  25. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  26. data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
  27. data/lib/arjdbc/postgresql/column.rb +10 -599
  28. data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
  29. data/lib/arjdbc/postgresql/name.rb +24 -0
  30. data/lib/arjdbc/postgresql/oid_types.rb +25 -110
  31. data/lib/arjdbc/sqlite3/adapter.rb +171 -170
  32. data/lib/arjdbc/tasks/database_tasks.rb +1 -3
  33. data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
  34. data/lib/arjdbc/version.rb +1 -1
  35. data/pom.xml +3 -3
  36. data/rakelib/02-test.rake +0 -12
  37. data/rakelib/compile.rake +1 -1
  38. data/rakelib/db.rake +7 -5
  39. data/rakelib/rails.rake +63 -64
  40. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
  41. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
  42. data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
  43. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
  44. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
  45. data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
  46. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
  47. metadata +20 -34
  48. data/Appraisals +0 -41
  49. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
  50. data/lib/arjdbc/common_jdbc_methods.rb +0 -89
  51. data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
  52. data/lib/arjdbc/mysql/column.rb +0 -162
  53. data/lib/arjdbc/mysql/explain_support.rb +0 -82
  54. data/lib/arjdbc/mysql/schema_creation.rb +0 -58
  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/oracle.rb +0 -4
  59. data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +0 -21
  60. data/lib/arjdbc/postgresql/base/oid.rb +0 -412
  61. data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
  62. data/lib/arjdbc/postgresql/explain_support.rb +0 -53
  63. data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
  64. data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
  65. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
  66. data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
  67. data/src/java/arjdbc/oracle/OracleModule.java +0 -75
  68. 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
@@ -1,65 +0,0 @@
1
- require 'arjdbc/tasks/jdbc_database_tasks'
2
-
3
- module ArJdbc
4
- module Tasks
5
- class OracleDatabaseTasks < JdbcDatabaseTasks
6
-
7
- def create
8
- print "Please provide the SYSTEM password for your oracle installation\n>"
9
- system_password = $stdin.gets.strip
10
- establish_connection(config.merge('username' => 'SYSTEM', 'password' => system_password))
11
- unless ( config = self.config ).key?('username')
12
- config = config_from_url(config['url']) if config['url']
13
- end
14
- begin
15
- connection.execute "CREATE USER #{config['username']} IDENTIFIED BY #{config['password']}"
16
- rescue => e
17
- if e.message =~ /ORA-01920/ # user name conflicts with another user or role name
18
- connection.execute "ALTER USER #{config['username']} IDENTIFIED BY #{config['password']}"
19
- else
20
- raise e
21
- end
22
- end
23
- connection.execute "GRANT unlimited tablespace TO #{config['username']}"
24
- connection.execute "GRANT create session TO #{config['username']}"
25
- connection.execute "GRANT create table TO #{config['username']}"
26
- connection.execute "GRANT create sequence TO #{config['username']}"
27
- end
28
-
29
- def drop
30
- self.class.load_enhanced_structure_dump
31
- establish_connection(config)
32
- connection.execute_structure_dump(connection.full_drop)
33
- end
34
-
35
- def purge
36
- self.class.load_enhanced_structure_dump
37
- establish_connection(:test)
38
- connection.execute_structure_dump(connection.full_drop)
39
- connection.execute("PURGE RECYCLEBIN") rescue nil
40
- end
41
-
42
- def structure_dump(filename)
43
- self.class.load_enhanced_structure_dump
44
- establish_connection(config)
45
- File.open(filename, "w:utf-8") { |f| f << connection.structure_dump }
46
- end
47
-
48
- def structure_load(filename)
49
- self.class.load_enhanced_structure_dump
50
- establish_connection(config)
51
- connection.execute_structure_dump(File.read(filename))
52
- end
53
-
54
- def self.load_enhanced_structure_dump
55
- unless defined? ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
56
- ActiveRecord::ConnectionAdapters.module_eval do
57
- const_set :OracleEnhancedAdapter, ActiveRecord::ConnectionAdapters::OracleAdapter
58
- end
59
- end
60
- require 'arjdbc/tasks/oracle/enhanced_structure_dump'
61
- end
62
-
63
- end
64
- end
65
- end
@@ -1,75 +0,0 @@
1
- /*
2
- * The MIT License
3
- *
4
- * Copyright 2013-2014 Karol Bucek.
5
- *
6
- * Permission is hereby granted, free of charge, to any person obtaining a copy
7
- * of this software and associated documentation files (the "Software"), to deal
8
- * in the Software without restriction, including without limitation the rights
9
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- * copies of the Software, and to permit persons to whom the Software is
11
- * furnished to do so, subject to the following conditions:
12
- *
13
- * The above copyright notice and this permission notice shall be included in
14
- * all copies or substantial portions of the Software.
15
- *
16
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- * THE SOFTWARE.
23
- */
24
- package arjdbc.oracle;
25
-
26
- import static arjdbc.util.QuotingUtils.BYTES_0;
27
- import static arjdbc.util.QuotingUtils.BYTES_1;
28
- import static arjdbc.util.QuotingUtils.quoteCharWith;
29
-
30
- import org.jruby.RubyModule;
31
- import org.jruby.RubyString;
32
- import org.jruby.anno.JRubyMethod;
33
- import org.jruby.runtime.ThreadContext;
34
- import org.jruby.runtime.builtin.IRubyObject;
35
-
36
- /**
37
- * ArJdbc::Oracle
38
- *
39
- * @author kares
40
- */
41
- public class OracleModule {
42
-
43
- public static RubyModule load(final RubyModule arJdbc) {
44
- RubyModule oracle = arJdbc.defineModuleUnder("Oracle");
45
- oracle.defineAnnotatedMethods( OracleModule.class );
46
- return oracle;
47
- }
48
-
49
- @JRubyMethod(name = "quote_string", required = 1)
50
- public static IRubyObject quote_string(
51
- final ThreadContext context,
52
- final IRubyObject self,
53
- final IRubyObject string) { // string.gsub("'", "''") :
54
- final char single = '\'';
55
- final RubyString quoted = quoteCharWith(
56
- context, (RubyString) string, single, single
57
- );
58
- return quoted;
59
- }
60
-
61
- @JRubyMethod(name = "quoted_true", required = 0)
62
- public static IRubyObject quoted_true(
63
- final ThreadContext context,
64
- final IRubyObject self) {
65
- return RubyString.newString(context.getRuntime(), BYTES_1);
66
- }
67
-
68
- @JRubyMethod(name = "quoted_false", required = 0)
69
- public static IRubyObject quoted_false(
70
- final ThreadContext context,
71
- final IRubyObject self) {
72
- return RubyString.newString(context.getRuntime(), BYTES_0);
73
- }
74
-
75
- }