activerecord-jdbc-adapter 5.0.pre1 → 50.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.
Potentially problematic release.
This version of activerecord-jdbc-adapter might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.gitignore +1 -2
- data/.travis.yml +15 -416
- data/Gemfile +35 -37
- data/README.md +23 -118
- data/RUNNING_TESTS.md +31 -26
- data/Rakefile +2 -3
- data/lib/arjdbc/abstract/connection_management.rb +21 -0
- data/lib/arjdbc/abstract/core.rb +62 -0
- data/lib/arjdbc/abstract/database_statements.rb +46 -0
- data/lib/arjdbc/abstract/statement_cache.rb +58 -0
- data/lib/arjdbc/abstract/transaction_support.rb +86 -0
- data/lib/arjdbc/derby/adapter.rb +6 -1
- data/lib/arjdbc/discover.rb +0 -7
- data/lib/arjdbc/firebird/adapter.rb +2 -2
- data/lib/arjdbc/jdbc.rb +2 -2
- data/lib/arjdbc/jdbc/adapter.rb +10 -252
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/connection.rb +6 -0
- data/lib/arjdbc/mysql/adapter.rb +82 -946
- data/lib/arjdbc/mysql/connection_methods.rb +4 -2
- data/lib/arjdbc/postgresql/adapter.rb +270 -970
- data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
- data/lib/arjdbc/postgresql/column.rb +10 -599
- data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
- data/lib/arjdbc/postgresql/name.rb +24 -0
- data/lib/arjdbc/postgresql/oid_types.rb +28 -109
- data/lib/arjdbc/sqlite3/adapter.rb +18 -42
- data/lib/arjdbc/tasks/database_tasks.rb +1 -3
- data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +3 -3
- data/rakelib/02-test.rake +0 -12
- data/rakelib/compile.rake +1 -1
- data/rakelib/db.rake +7 -5
- data/rakelib/rails.rake +67 -64
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
- data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
- metadata +16 -29
- data/Appraisals +0 -41
- data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
- data/lib/arjdbc/common_jdbc_methods.rb +0 -89
- data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
- data/lib/arjdbc/mysql/column.rb +0 -162
- data/lib/arjdbc/mysql/explain_support.rb +0 -82
- data/lib/arjdbc/mysql/schema_creation.rb +0 -58
- data/lib/arjdbc/oracle.rb +0 -4
- data/lib/arjdbc/oracle/adapter.rb +0 -952
- data/lib/arjdbc/oracle/column.rb +0 -126
- data/lib/arjdbc/oracle/connection_methods.rb +0 -21
- data/lib/arjdbc/postgresql/base/oid.rb +0 -412
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
- data/lib/arjdbc/postgresql/explain_support.rb +0 -53
- data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
- data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
- data/src/java/arjdbc/oracle/OracleModule.java +0 -75
- 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,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
|