activerecord-jdbc-adapter-onsite 1.2.2
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.
- data/.gitignore +22 -0
- data/.travis.yml +14 -0
- data/Appraisals +16 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +45 -0
- data/History.txt +488 -0
- data/LICENSE.txt +21 -0
- data/README.rdoc +214 -0
- data/Rakefile +62 -0
- data/activerecord-jdbc-adapter.gemspec +23 -0
- data/bench/bench_attributes.rb +13 -0
- data/bench/bench_attributes_new.rb +14 -0
- data/bench/bench_create.rb +12 -0
- data/bench/bench_find_all.rb +12 -0
- data/bench/bench_find_all_mt.rb +25 -0
- data/bench/bench_model.rb +85 -0
- data/bench/bench_new.rb +12 -0
- data/bench/bench_new_valid.rb +12 -0
- data/bench/bench_valid.rb +13 -0
- data/gemfiles/rails23.gemfile +10 -0
- data/gemfiles/rails23.gemfile.lock +38 -0
- data/gemfiles/rails30.gemfile +9 -0
- data/gemfiles/rails30.gemfile.lock +33 -0
- data/gemfiles/rails31.gemfile +9 -0
- data/gemfiles/rails31.gemfile.lock +35 -0
- data/gemfiles/rails32.gemfile +9 -0
- data/gemfiles/rails32.gemfile.lock +35 -0
- data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
- data/lib/activerecord-jdbc-adapter.rb +8 -0
- data/lib/arel/engines/sql/compilers/db2_compiler.rb +9 -0
- data/lib/arel/engines/sql/compilers/derby_compiler.rb +6 -0
- data/lib/arel/engines/sql/compilers/h2_compiler.rb +6 -0
- data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +15 -0
- data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +6 -0
- data/lib/arel/engines/sql/compilers/mssql_compiler.rb +46 -0
- data/lib/arel/visitors/compat.rb +13 -0
- data/lib/arel/visitors/db2.rb +17 -0
- data/lib/arel/visitors/derby.rb +32 -0
- data/lib/arel/visitors/firebird.rb +24 -0
- data/lib/arel/visitors/hsqldb.rb +26 -0
- data/lib/arel/visitors/sql_server.rb +46 -0
- data/lib/arjdbc.rb +24 -0
- data/lib/arjdbc/db2.rb +2 -0
- data/lib/arjdbc/db2/adapter.rb +541 -0
- data/lib/arjdbc/derby.rb +7 -0
- data/lib/arjdbc/derby/adapter.rb +358 -0
- data/lib/arjdbc/derby/connection_methods.rb +19 -0
- data/lib/arjdbc/discover.rb +92 -0
- data/lib/arjdbc/firebird.rb +2 -0
- data/lib/arjdbc/firebird/adapter.rb +140 -0
- data/lib/arjdbc/h2.rb +4 -0
- data/lib/arjdbc/h2/adapter.rb +54 -0
- data/lib/arjdbc/h2/connection_methods.rb +13 -0
- data/lib/arjdbc/hsqldb.rb +4 -0
- data/lib/arjdbc/hsqldb/adapter.rb +184 -0
- data/lib/arjdbc/hsqldb/connection_methods.rb +15 -0
- data/lib/arjdbc/informix.rb +3 -0
- data/lib/arjdbc/informix/adapter.rb +142 -0
- data/lib/arjdbc/informix/connection_methods.rb +11 -0
- data/lib/arjdbc/jdbc.rb +2 -0
- data/lib/arjdbc/jdbc/adapter.rb +356 -0
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/base_ext.rb +15 -0
- data/lib/arjdbc/jdbc/callbacks.rb +44 -0
- data/lib/arjdbc/jdbc/column.rb +47 -0
- data/lib/arjdbc/jdbc/compatibility.rb +51 -0
- data/lib/arjdbc/jdbc/connection.rb +134 -0
- data/lib/arjdbc/jdbc/connection_methods.rb +16 -0
- data/lib/arjdbc/jdbc/core_ext.rb +24 -0
- data/lib/arjdbc/jdbc/discover.rb +18 -0
- data/lib/arjdbc/jdbc/driver.rb +35 -0
- data/lib/arjdbc/jdbc/extension.rb +47 -0
- data/lib/arjdbc/jdbc/java.rb +14 -0
- data/lib/arjdbc/jdbc/jdbc.rake +131 -0
- data/lib/arjdbc/jdbc/missing_functionality_helper.rb +88 -0
- data/lib/arjdbc/jdbc/quoted_primary_key.rb +28 -0
- data/lib/arjdbc/jdbc/railtie.rb +9 -0
- data/lib/arjdbc/jdbc/rake_tasks.rb +10 -0
- data/lib/arjdbc/jdbc/require_driver.rb +16 -0
- data/lib/arjdbc/jdbc/type_converter.rb +126 -0
- data/lib/arjdbc/mimer.rb +2 -0
- data/lib/arjdbc/mimer/adapter.rb +142 -0
- data/lib/arjdbc/mssql.rb +4 -0
- data/lib/arjdbc/mssql/adapter.rb +477 -0
- data/lib/arjdbc/mssql/connection_methods.rb +31 -0
- data/lib/arjdbc/mssql/limit_helpers.rb +101 -0
- data/lib/arjdbc/mssql/lock_helpers.rb +72 -0
- data/lib/arjdbc/mssql/tsql_helper.rb +61 -0
- data/lib/arjdbc/mysql.rb +4 -0
- data/lib/arjdbc/mysql/adapter.rb +505 -0
- data/lib/arjdbc/mysql/connection_methods.rb +28 -0
- data/lib/arjdbc/oracle.rb +3 -0
- data/lib/arjdbc/oracle/adapter.rb +432 -0
- data/lib/arjdbc/oracle/connection_methods.rb +12 -0
- data/lib/arjdbc/postgresql.rb +4 -0
- data/lib/arjdbc/postgresql/adapter.rb +861 -0
- data/lib/arjdbc/postgresql/connection_methods.rb +23 -0
- data/lib/arjdbc/sqlite3.rb +4 -0
- data/lib/arjdbc/sqlite3/adapter.rb +389 -0
- data/lib/arjdbc/sqlite3/connection_methods.rb +35 -0
- data/lib/arjdbc/sybase.rb +2 -0
- data/lib/arjdbc/sybase/adapter.rb +46 -0
- data/lib/arjdbc/version.rb +8 -0
- data/lib/generators/jdbc/USAGE +10 -0
- data/lib/generators/jdbc/jdbc_generator.rb +9 -0
- data/lib/jdbc_adapter.rb +2 -0
- data/lib/jdbc_adapter/rake_tasks.rb +3 -0
- data/lib/jdbc_adapter/version.rb +3 -0
- data/lib/pg.rb +26 -0
- data/pom.xml +57 -0
- data/rails_generators/jdbc_generator.rb +15 -0
- data/rails_generators/templates/config/initializers/jdbc.rb +7 -0
- data/rails_generators/templates/lib/tasks/jdbc.rake +8 -0
- data/rakelib/bundler_ext.rb +11 -0
- data/rakelib/compile.rake +23 -0
- data/rakelib/db.rake +39 -0
- data/rakelib/rails.rake +41 -0
- data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +69 -0
- data/src/java/arjdbc/derby/DerbyModule.java +324 -0
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +70 -0
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +74 -0
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +68 -0
- data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +36 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1346 -0
- data/src/java/arjdbc/jdbc/SQLBlock.java +48 -0
- data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +127 -0
- data/src/java/arjdbc/mysql/MySQLModule.java +134 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +161 -0
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +85 -0
- data/src/java/arjdbc/postgresql/PostgresqlRubyJdbcConnection.java +82 -0
- data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +126 -0
- data/test/abstract_db_create.rb +135 -0
- data/test/activerecord/connection_adapters/type_conversion_test.rb +31 -0
- data/test/activerecord/connections/native_jdbc_mysql/connection.rb +25 -0
- data/test/activerecord/jall.sh +7 -0
- data/test/activerecord/jtest.sh +3 -0
- data/test/db/db2.rb +11 -0
- data/test/db/derby.rb +12 -0
- data/test/db/h2.rb +11 -0
- data/test/db/hsqldb.rb +13 -0
- data/test/db/informix.rb +11 -0
- data/test/db/jdbc.rb +12 -0
- data/test/db/jndi_config.rb +40 -0
- data/test/db/logger.rb +3 -0
- data/test/db/mssql.rb +9 -0
- data/test/db/mysql.rb +10 -0
- data/test/db/oracle.rb +34 -0
- data/test/db/postgres.rb +18 -0
- data/test/db/sqlite3.rb +11 -0
- data/test/db2_reset_column_information_test.rb +8 -0
- data/test/db2_simple_test.rb +66 -0
- data/test/derby_migration_test.rb +68 -0
- data/test/derby_multibyte_test.rb +12 -0
- data/test/derby_reset_column_information_test.rb +8 -0
- data/test/derby_row_locking_test.rb +9 -0
- data/test/derby_simple_test.rb +139 -0
- data/test/generic_jdbc_connection_test.rb +29 -0
- data/test/h2_change_column_test.rb +68 -0
- data/test/h2_simple_test.rb +41 -0
- data/test/has_many_through.rb +79 -0
- data/test/helper.rb +108 -0
- data/test/hsqldb_simple_test.rb +6 -0
- data/test/informix_simple_test.rb +48 -0
- data/test/jdbc_common.rb +28 -0
- data/test/jndi_callbacks_test.rb +36 -0
- data/test/jndi_test.rb +25 -0
- data/test/manualTestDatabase.rb +191 -0
- data/test/models/add_not_null_column_to_table.rb +9 -0
- data/test/models/auto_id.rb +15 -0
- data/test/models/custom_pk_name.rb +14 -0
- data/test/models/data_types.rb +30 -0
- data/test/models/entry.rb +40 -0
- data/test/models/mixed_case.rb +22 -0
- data/test/models/reserved_word.rb +15 -0
- data/test/models/string_id.rb +17 -0
- data/test/models/thing.rb +16 -0
- data/test/models/validates_uniqueness_of_string.rb +19 -0
- data/test/mssql_db_create_test.rb +26 -0
- data/test/mssql_identity_insert_test.rb +19 -0
- data/test/mssql_ignore_system_views_test.rb +27 -0
- data/test/mssql_legacy_types_test.rb +58 -0
- data/test/mssql_limit_offset_test.rb +136 -0
- data/test/mssql_multibyte_test.rb +18 -0
- data/test/mssql_null_test.rb +14 -0
- data/test/mssql_reset_column_information_test.rb +8 -0
- data/test/mssql_row_locking_sql_test.rb +159 -0
- data/test/mssql_row_locking_test.rb +9 -0
- data/test/mssql_simple_test.rb +55 -0
- data/test/mysql_db_create_test.rb +27 -0
- data/test/mysql_index_length_test.rb +58 -0
- data/test/mysql_info_test.rb +123 -0
- data/test/mysql_multibyte_test.rb +10 -0
- data/test/mysql_nonstandard_primary_key_test.rb +42 -0
- data/test/mysql_reset_column_information_test.rb +8 -0
- data/test/mysql_simple_test.rb +125 -0
- data/test/oracle_reset_column_information_test.rb +8 -0
- data/test/oracle_simple_test.rb +18 -0
- data/test/oracle_specific_test.rb +83 -0
- data/test/postgres_db_create_test.rb +32 -0
- data/test/postgres_drop_db_test.rb +16 -0
- data/test/postgres_information_schema_leak_test.rb +29 -0
- data/test/postgres_mixed_case_test.rb +29 -0
- data/test/postgres_native_type_mapping_test.rb +93 -0
- data/test/postgres_nonseq_pkey_test.rb +38 -0
- data/test/postgres_reserved_test.rb +22 -0
- data/test/postgres_reset_column_information_test.rb +8 -0
- data/test/postgres_schema_search_path_test.rb +48 -0
- data/test/postgres_simple_test.rb +168 -0
- data/test/postgres_table_alias_length_test.rb +15 -0
- data/test/postgres_type_conversion_test.rb +34 -0
- data/test/row_locking.rb +90 -0
- data/test/simple.rb +731 -0
- data/test/sqlite3_reset_column_information_test.rb +8 -0
- data/test/sqlite3_simple_test.rb +316 -0
- data/test/sybase_jtds_simple_test.rb +28 -0
- data/test/sybase_reset_column_information_test.rb +8 -0
- metadata +288 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Don't need to load native mysql adapter
|
|
2
|
+
$LOADED_FEATURES << "active_record/connection_adapters/mysql_adapter.rb"
|
|
3
|
+
$LOADED_FEATURES << "active_record/connection_adapters/mysql2_adapter.rb"
|
|
4
|
+
|
|
5
|
+
class ActiveRecord::Base
|
|
6
|
+
class << self
|
|
7
|
+
def mysql_connection(config)
|
|
8
|
+
require "arjdbc/mysql"
|
|
9
|
+
config[:port] ||= 3306
|
|
10
|
+
options = (config[:options] ||= {})
|
|
11
|
+
options['zeroDateTimeBehavior'] ||= 'convertToNull'
|
|
12
|
+
options['jdbcCompliantTruncation'] ||= 'false'
|
|
13
|
+
options['useUnicode'] ||= 'true'
|
|
14
|
+
options['characterEncoding'] = config[:encoding] || 'utf8'
|
|
15
|
+
config[:url] ||= "jdbc:mysql://#{config[:host]}:#{config[:port]}/#{config[:database]}"
|
|
16
|
+
config[:driver] ||= "com.mysql.jdbc.Driver"
|
|
17
|
+
config[:adapter_class] = ActiveRecord::ConnectionAdapters::MysqlAdapter
|
|
18
|
+
config[:adapter_spec] = ::ArJdbc::MySQL
|
|
19
|
+
connection = jdbc_connection(config)
|
|
20
|
+
::ArJdbc::MySQL.kill_cancel_timer(connection.raw_connection)
|
|
21
|
+
connection
|
|
22
|
+
end
|
|
23
|
+
alias_method :jdbcmysql_connection, :mysql_connection
|
|
24
|
+
alias_method :mysql2_connection, :mysql_connection
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
module ActiveRecord::ConnectionAdapters
|
|
2
|
+
OracleAdapter = Class.new(AbstractAdapter) unless const_defined?(:OracleAdapter)
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
module ::ArJdbc
|
|
6
|
+
module Oracle
|
|
7
|
+
def self.extended(mod)
|
|
8
|
+
unless defined?(@lob_callback_added)
|
|
9
|
+
ActiveRecord::Base.class_eval do
|
|
10
|
+
def after_save_with_oracle_lob
|
|
11
|
+
self.class.columns.select { |c| c.sql_type =~ /LOB\(|LOB$/i }.each do |c|
|
|
12
|
+
value = self[c.name]
|
|
13
|
+
if respond_to?(:unserializable_attribute?)
|
|
14
|
+
value = value.to_yaml if unserializable_attribute?(c.name, c)
|
|
15
|
+
else
|
|
16
|
+
value = value.to_yaml if value.is_a?(Hash)
|
|
17
|
+
end
|
|
18
|
+
next if value.nil? || (value == '')
|
|
19
|
+
|
|
20
|
+
connection.write_large_object(c.type == :binary, c.name, self.class.table_name, self.class.primary_key, quote_value(id), value)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
ActiveRecord::Base.after_save :after_save_with_oracle_lob
|
|
26
|
+
@lob_callback_added = true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
unless ActiveRecord::ConnectionAdapters::AbstractAdapter.instance_methods(false).detect {|m| m.to_s == "prefetch_primary_key?"}
|
|
30
|
+
require 'arjdbc/jdbc/quoted_primary_key'
|
|
31
|
+
ActiveRecord::Base.extend ArJdbc::QuotedPrimaryKeyExtension
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
(class << mod; self; end).class_eval do
|
|
35
|
+
alias_chained_method :insert, :query_dirty, :ora_insert
|
|
36
|
+
alias_chained_method :columns, :query_cache, :ora_columns
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.column_selector
|
|
41
|
+
[/oracle/i, lambda {|cfg,col| col.extend(::ArJdbc::Oracle::Column)}]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.jdbc_connection_class
|
|
45
|
+
::ActiveRecord::ConnectionAdapters::OracleJdbcConnection
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module Column
|
|
49
|
+
def primary=(val)
|
|
50
|
+
super
|
|
51
|
+
if val && @sql_type =~ /^NUMBER$/i
|
|
52
|
+
@type = :integer
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def type_cast(value)
|
|
57
|
+
return nil if value.nil?
|
|
58
|
+
case type
|
|
59
|
+
when :datetime then ArJdbc::Oracle::Column.string_to_time(value, self.class)
|
|
60
|
+
else
|
|
61
|
+
super
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def extract_limit(sql_type)
|
|
66
|
+
case sql_type
|
|
67
|
+
when /^(clob|date)/i; nil
|
|
68
|
+
else super
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def type_cast_code(var_name)
|
|
73
|
+
case type
|
|
74
|
+
when :datetime then "ArJdbc::Oracle::Column.string_to_time(#{var_name}, self.class)"
|
|
75
|
+
else
|
|
76
|
+
super
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.string_to_time(string, klass)
|
|
81
|
+
time = klass.string_to_time(string)
|
|
82
|
+
guess_date_or_time(time)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def self.guess_date_or_time(value)
|
|
86
|
+
return value if Date === value
|
|
87
|
+
(value && value.hour == 0 && value.min == 0 && value.sec == 0) ?
|
|
88
|
+
Date.new(value.year, value.month, value.day) : value
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
def simplified_type(field_type)
|
|
93
|
+
case field_type
|
|
94
|
+
when /^number\(1\)$/i then :boolean
|
|
95
|
+
when /char/i then :string
|
|
96
|
+
when /float|double/i then :float
|
|
97
|
+
when /int/i then :integer
|
|
98
|
+
when /num|dec|real/i then extract_scale(field_type) == 0 ? :integer : :decimal
|
|
99
|
+
when /date|time/i then :datetime
|
|
100
|
+
when /clob/i then :text
|
|
101
|
+
when /blob/i then :binary
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Post process default value from JDBC into a Rails-friendly format (columns{-internal})
|
|
106
|
+
def default_value(value)
|
|
107
|
+
return nil unless value
|
|
108
|
+
|
|
109
|
+
# Not sure why we need this for Oracle?
|
|
110
|
+
value = value.strip
|
|
111
|
+
|
|
112
|
+
return nil if value == "null"
|
|
113
|
+
|
|
114
|
+
# sysdate default should be treated like a null value
|
|
115
|
+
return nil if value.downcase == "sysdate"
|
|
116
|
+
|
|
117
|
+
# jdbc returns column default strings with actual single quotes around the value.
|
|
118
|
+
return $1 if value =~ /^'(.*)'$/
|
|
119
|
+
|
|
120
|
+
value
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def adapter_name
|
|
125
|
+
'Oracle'
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def self.arel2_visitors(config)
|
|
129
|
+
{ 'oracle' => Arel::Visitors::Oracle }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def prefetch_primary_key?(table_name = nil)
|
|
133
|
+
columns(table_name).detect {|c| c.primary } if table_name
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def table_alias_length
|
|
137
|
+
30
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def default_sequence_name(table, column = nil) #:nodoc:
|
|
141
|
+
"#{table}_seq"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def create_table(name, options = {}) #:nodoc:
|
|
145
|
+
super(name, options)
|
|
146
|
+
seq_name = options[:sequence_name] || default_sequence_name(name)
|
|
147
|
+
start_value = options[:sequence_start_value] || 10000
|
|
148
|
+
raise ActiveRecord::StatementInvalid.new("name #{seq_name} too long") if seq_name.length > table_alias_length
|
|
149
|
+
execute "CREATE SEQUENCE #{seq_name} START WITH #{start_value}" unless options[:id] == false
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def rename_table(name, new_name) #:nodoc:
|
|
153
|
+
execute "RENAME #{name} TO #{new_name}"
|
|
154
|
+
execute "RENAME #{name}_seq TO #{new_name}_seq" rescue nil
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def drop_table(name, options = {}) #:nodoc:
|
|
158
|
+
super(name) rescue nil
|
|
159
|
+
seq_name = options[:sequence_name] || default_sequence_name(name)
|
|
160
|
+
execute "DROP SEQUENCE #{seq_name}" rescue nil
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def recreate_database(name)
|
|
164
|
+
tables.each{ |table| drop_table(table) }
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def drop_database(name)
|
|
168
|
+
recreate_database(name)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def next_sequence_value(sequence_name)
|
|
172
|
+
# avoid #select or #select_one so that the sequence values aren't cached
|
|
173
|
+
execute("select #{sequence_name}.nextval id from dual").first['id'].to_i
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def sql_literal?(value)
|
|
177
|
+
defined?(::Arel::SqlLiteral) && ::Arel::SqlLiteral === value
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def ora_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) #:nodoc:
|
|
181
|
+
if (id_value && !sql_literal?(id_value)) || pk.nil?
|
|
182
|
+
# Pre-assigned id or table without a primary key
|
|
183
|
+
# Presence of #to_sql means an Arel literal bind variable
|
|
184
|
+
# that should use #execute_id_insert below
|
|
185
|
+
execute sql, name, binds
|
|
186
|
+
else
|
|
187
|
+
# Assume the sql contains a bind-variable for the id
|
|
188
|
+
# Extract the table from the insert sql. Yuck.
|
|
189
|
+
table = sql.split(" ", 4)[2].gsub('"', '')
|
|
190
|
+
sequence_name ||= default_sequence_name(table)
|
|
191
|
+
id_value = next_sequence_value(sequence_name)
|
|
192
|
+
log(sql, name) do
|
|
193
|
+
@connection.execute_id_insert(sql,id_value)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
id_value
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def indexes(table, name = nil)
|
|
200
|
+
@connection.indexes(table, name, @connection.connection.meta_data.user_name)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def _execute(sql, name = nil)
|
|
204
|
+
case sql.strip
|
|
205
|
+
when /\A\(?\s*(select|show)/i then
|
|
206
|
+
@connection.execute_query(sql)
|
|
207
|
+
else
|
|
208
|
+
@connection.execute_update(sql)
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def modify_types(tp)
|
|
213
|
+
tp[:primary_key] = "NUMBER(38) NOT NULL PRIMARY KEY"
|
|
214
|
+
tp[:integer] = { :name => "NUMBER", :limit => 38 }
|
|
215
|
+
tp[:datetime] = { :name => "DATE" }
|
|
216
|
+
tp[:timestamp] = { :name => "DATE" }
|
|
217
|
+
tp[:time] = { :name => "DATE" }
|
|
218
|
+
tp[:date] = { :name => "DATE" }
|
|
219
|
+
tp
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def add_limit_offset!(sql, options) #:nodoc:
|
|
223
|
+
offset = options[:offset] || 0
|
|
224
|
+
|
|
225
|
+
if limit = options[:limit]
|
|
226
|
+
sql.replace "select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_ where rownum <= #{offset+limit}) where raw_rnum_ > #{offset}"
|
|
227
|
+
elsif offset > 0
|
|
228
|
+
sql.replace "select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_) where raw_rnum_ > #{offset}"
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def current_database #:nodoc:
|
|
233
|
+
select_one("select sys_context('userenv','db_name') db from dual")["db"]
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def remove_index(table_name, options = {}) #:nodoc:
|
|
237
|
+
execute "DROP INDEX #{index_name(table_name, options)}"
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def change_column_default(table_name, column_name, default) #:nodoc:
|
|
241
|
+
execute "ALTER TABLE #{table_name} MODIFY #{column_name} DEFAULT #{quote(default)}"
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def add_column_options!(sql, options) #:nodoc:
|
|
245
|
+
# handle case of defaults for CLOB columns, which would otherwise get "quoted" incorrectly
|
|
246
|
+
if options_include_default?(options) && (column = options[:column]) && column.type == :text
|
|
247
|
+
sql << " DEFAULT #{quote(options.delete(:default))}"
|
|
248
|
+
end
|
|
249
|
+
super
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
|
253
|
+
change_column_sql = "ALTER TABLE #{table_name} MODIFY #{column_name} #{type_to_sql(type, options[:limit])}"
|
|
254
|
+
add_column_options!(change_column_sql, options)
|
|
255
|
+
execute(change_column_sql)
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
|
259
|
+
execute "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} to #{new_column_name}"
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def remove_column(table_name, column_name) #:nodoc:
|
|
263
|
+
execute "ALTER TABLE #{table_name} DROP COLUMN #{column_name}"
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def structure_dump #:nodoc:
|
|
267
|
+
s = select_all("select sequence_name from user_sequences").inject("") do |structure, seq|
|
|
268
|
+
structure << "create sequence #{seq.to_a.first.last};\n\n"
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
select_all("select table_name from user_tables").inject(s) do |structure, table|
|
|
272
|
+
ddl = "create table #{table.to_a.first.last} (\n "
|
|
273
|
+
cols = select_all(%Q{
|
|
274
|
+
select column_name, data_type, data_length, data_precision, data_scale, data_default, nullable
|
|
275
|
+
from user_tab_columns
|
|
276
|
+
where table_name = '#{table.to_a.first.last}'
|
|
277
|
+
order by column_id
|
|
278
|
+
}).map do |row|
|
|
279
|
+
row = row.inject({}) do |h,args|
|
|
280
|
+
h[args[0].downcase] = args[1]
|
|
281
|
+
h
|
|
282
|
+
end
|
|
283
|
+
col = "#{row['column_name'].downcase} #{row['data_type'].downcase}"
|
|
284
|
+
if row['data_type'] =='NUMBER' and !row['data_precision'].nil?
|
|
285
|
+
col << "(#{row['data_precision'].to_i}"
|
|
286
|
+
col << ",#{row['data_scale'].to_i}" if !row['data_scale'].nil?
|
|
287
|
+
col << ')'
|
|
288
|
+
elsif row['data_type'].include?('CHAR')
|
|
289
|
+
col << "(#{row['data_length'].to_i})"
|
|
290
|
+
end
|
|
291
|
+
col << " default #{row['data_default']}" if !row['data_default'].nil?
|
|
292
|
+
col << ' not null' if row['nullable'] == 'N'
|
|
293
|
+
col
|
|
294
|
+
end
|
|
295
|
+
ddl << cols.join(",\n ")
|
|
296
|
+
ddl << ");\n\n"
|
|
297
|
+
structure << ddl
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def structure_drop #:nodoc:
|
|
302
|
+
s = select_all("select sequence_name from user_sequences").inject("") do |drop, seq|
|
|
303
|
+
drop << "drop sequence #{seq.to_a.first.last};\n\n"
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
select_all("select table_name from user_tables").inject(s) do |drop, table|
|
|
307
|
+
drop << "drop table #{table.to_a.first.last} cascade constraints;\n\n"
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
|
|
312
|
+
#
|
|
313
|
+
# Oracle requires the ORDER BY columns to be in the SELECT list for DISTINCT
|
|
314
|
+
# queries. However, with those columns included in the SELECT DISTINCT list, you
|
|
315
|
+
# won't actually get a distinct list of the column you want (presuming the column
|
|
316
|
+
# has duplicates with multiple values for the ordered-by columns. So we use the
|
|
317
|
+
# FIRST_VALUE function to get a single (first) value for each column, effectively
|
|
318
|
+
# making every row the same.
|
|
319
|
+
#
|
|
320
|
+
# distinct("posts.id", "posts.created_at desc")
|
|
321
|
+
def distinct(columns, order_by)
|
|
322
|
+
return "DISTINCT #{columns}" if order_by.blank?
|
|
323
|
+
|
|
324
|
+
# construct a valid DISTINCT clause, ie. one that includes the ORDER BY columns, using
|
|
325
|
+
# FIRST_VALUE such that the inclusion of these columns doesn't invalidate the DISTINCT
|
|
326
|
+
order_columns = order_by.split(',').map { |s| s.strip }.reject(&:blank?)
|
|
327
|
+
order_columns = order_columns.zip((0...order_columns.size).to_a).map do |c, i|
|
|
328
|
+
"FIRST_VALUE(#{c.split.first}) OVER (PARTITION BY #{columns} ORDER BY #{c}) AS alias_#{i}__"
|
|
329
|
+
end
|
|
330
|
+
sql = "DISTINCT #{columns}, "
|
|
331
|
+
sql << order_columns * ", "
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# ORDER BY clause for the passed order option.
|
|
335
|
+
#
|
|
336
|
+
# Uses column aliases as defined by #distinct.
|
|
337
|
+
def add_order_by_for_association_limiting!(sql, options)
|
|
338
|
+
return sql if options[:order].blank?
|
|
339
|
+
|
|
340
|
+
order = options[:order].split(',').collect { |s| s.strip }.reject(&:blank?)
|
|
341
|
+
order.map! {|s| $1 if s =~ / (.*)/}
|
|
342
|
+
order = order.zip((0...order.size).to_a).map { |s,i| "alias_#{i}__ #{s}" }.join(', ')
|
|
343
|
+
|
|
344
|
+
sql << "ORDER BY #{order}"
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def tables
|
|
348
|
+
@connection.tables(nil, oracle_schema)
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def ora_columns(table_name, name=nil)
|
|
352
|
+
@connection.columns_internal(table_name, name, oracle_schema)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# QUOTING ==================================================
|
|
356
|
+
#
|
|
357
|
+
# see: abstract/quoting.rb
|
|
358
|
+
|
|
359
|
+
# See ACTIVERECORD_JDBC-33 for details -- better to not quote
|
|
360
|
+
# table names, esp. if they have schemas.
|
|
361
|
+
def quote_table_name(name) #:nodoc:
|
|
362
|
+
name.to_s
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
# Camelcase column names need to be quoted.
|
|
366
|
+
# Nonquoted identifiers can contain only alphanumeric characters from your
|
|
367
|
+
# database character set and the underscore (_), dollar sign ($), and pound sign (#).
|
|
368
|
+
# Database links can also contain periods (.) and "at" signs (@).
|
|
369
|
+
# Oracle strongly discourages you from using $ and # in nonquoted identifiers.
|
|
370
|
+
# Source: http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/sql_elements008.htm
|
|
371
|
+
def quote_column_name(name) #:nodoc:
|
|
372
|
+
name.to_s =~ /^[a-z0-9_$#]+$/ ? name.to_s : "\"#{name}\""
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def quote_string(string) #:nodoc:
|
|
376
|
+
string.gsub(/'/, "''")
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def quote(value, column = nil) #:nodoc:
|
|
380
|
+
# Arel 2 passes SqlLiterals through
|
|
381
|
+
return value if sql_literal?(value)
|
|
382
|
+
|
|
383
|
+
if column && [:text, :binary].include?(column.type)
|
|
384
|
+
if /(.*?)\([0-9]+\)/ =~ column.sql_type
|
|
385
|
+
%Q{empty_#{ $1.downcase }()}
|
|
386
|
+
else
|
|
387
|
+
%Q{empty_#{ column.sql_type.downcase rescue 'blob' }()}
|
|
388
|
+
end
|
|
389
|
+
else
|
|
390
|
+
if column.respond_to?(:primary) && column.primary && column.klass != String
|
|
391
|
+
return value.to_i.to_s
|
|
392
|
+
end
|
|
393
|
+
quoted = super
|
|
394
|
+
if value.acts_like?(:date)
|
|
395
|
+
quoted = %Q{DATE'#{quoted_date(value)}'}
|
|
396
|
+
elsif value.acts_like?(:time)
|
|
397
|
+
quoted = %Q{TIMESTAMP'#{quoted_date(value)}'}
|
|
398
|
+
end
|
|
399
|
+
quoted
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def quoted_true #:nodoc:
|
|
404
|
+
'1'
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
def quoted_false #:nodoc:
|
|
408
|
+
'0'
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
private
|
|
412
|
+
# In Oracle, schemas are usually created under your username:
|
|
413
|
+
# http://www.oracle.com/technology/obe/2day_dba/schema/schema.htm
|
|
414
|
+
# But allow separate configuration as "schema:" anyway (GH #53)
|
|
415
|
+
def oracle_schema
|
|
416
|
+
if @config[:schema]
|
|
417
|
+
@config[:schema].to_s
|
|
418
|
+
elsif @config[:username]
|
|
419
|
+
@config[:username].to_s
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def select(sql, name = nil, binds = [])
|
|
424
|
+
records = execute(sql, name, binds)
|
|
425
|
+
records.each do |col|
|
|
426
|
+
col.delete('raw_rnum_')
|
|
427
|
+
end
|
|
428
|
+
records
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|