activerecord-jdbc-adapter 0.6
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/History.txt +61 -0
- data/LICENSE +21 -0
- data/Manifest.txt +64 -0
- data/README.txt +116 -0
- data/Rakefile +146 -0
- data/lib/active_record/connection_adapters/derby_adapter.rb +13 -0
- data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/hsqldb_adapter.rb +13 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +575 -0
- data/lib/active_record/connection_adapters/jdbc_adapter_spec.rb +10 -0
- data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +13 -0
- data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +13 -0
- data/lib/jdbc_adapter.rb +32 -0
- data/lib/jdbc_adapter/jdbc_db2.rb +104 -0
- data/lib/jdbc_adapter/jdbc_derby.rb +362 -0
- data/lib/jdbc_adapter/jdbc_firebird.rb +109 -0
- data/lib/jdbc_adapter/jdbc_hsqldb.rb +168 -0
- data/lib/jdbc_adapter/jdbc_mimer.rb +134 -0
- data/lib/jdbc_adapter/jdbc_mssql.rb +356 -0
- data/lib/jdbc_adapter/jdbc_mysql.rb +168 -0
- data/lib/jdbc_adapter/jdbc_oracle.rb +340 -0
- data/lib/jdbc_adapter/jdbc_postgre.rb +347 -0
- data/lib/jdbc_adapter/missing_functionality_helper.rb +72 -0
- data/lib/jdbc_adapter/version.rb +5 -0
- data/lib/jdbc_adapter_internal.jar +0 -0
- data/lib/tasks/jdbc_databases.rake +72 -0
- data/src/java/JDBCDerbySpec.java +323 -0
- data/src/java/JDBCMySQLSpec.java +89 -0
- data/src/java/JdbcAdapterInternalService.java +953 -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/db/derby.rb +18 -0
- data/test/db/h2.rb +11 -0
- data/test/db/hsqldb.rb +15 -0
- data/test/db/jdbc.rb +11 -0
- data/test/db/jndi_config.rb +30 -0
- data/test/db/logger.rb +3 -0
- data/test/db/mysql.rb +9 -0
- data/test/db/postgres.rb +9 -0
- data/test/derby_multibyte_test.rb +12 -0
- data/test/derby_simple_test.rb +12 -0
- data/test/generic_jdbc_connection_test.rb +9 -0
- data/test/h2_simple_test.rb +7 -0
- data/test/hsqldb_simple_test.rb +6 -0
- data/test/jdbc_adapter/jdbc_db2_test.rb +21 -0
- data/test/jdbc_common.rb +6 -0
- data/test/jndi_test.rb +37 -0
- data/test/manualTestDatabase.rb +195 -0
- data/test/minirunit.rb +109 -0
- data/test/minirunit/testConnect.rb +14 -0
- data/test/minirunit/testH2.rb +73 -0
- data/test/minirunit/testHsqldb.rb +73 -0
- data/test/minirunit/testLoadActiveRecord.rb +3 -0
- data/test/minirunit/testMysql.rb +83 -0
- data/test/minirunit/testRawSelect.rb +24 -0
- data/test/models/auto_id.rb +18 -0
- data/test/models/data_types.rb +18 -0
- data/test/models/entry.rb +20 -0
- data/test/mysql_multibyte_test.rb +6 -0
- data/test/mysql_simple_test.rb +13 -0
- data/test/postgres_simple_test.rb +12 -0
- data/test/simple.rb +157 -0
- metadata +112 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
|
2
|
+
require 'jdbc_adapter/jdbc_mimer'
|
3
|
+
require 'jdbc_adapter/jdbc_hsqldb'
|
4
|
+
require 'jdbc_adapter/jdbc_oracle'
|
5
|
+
require 'jdbc_adapter/jdbc_postgre'
|
6
|
+
require 'jdbc_adapter/jdbc_mysql'
|
7
|
+
require 'jdbc_adapter/jdbc_derby'
|
8
|
+
require 'jdbc_adapter/jdbc_firebird'
|
9
|
+
require 'jdbc_adapter/jdbc_db2'
|
10
|
+
require 'jdbc_adapter/jdbc_mssql'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_record/connection_adapters/jdbc_adapter'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
tried_gem = false
|
2
|
+
begin
|
3
|
+
require "jdbc/mysql"
|
4
|
+
rescue LoadError
|
5
|
+
unless tried_gem
|
6
|
+
require 'rubygems'
|
7
|
+
gem "jdbc-mysql"
|
8
|
+
tried_gem = true
|
9
|
+
retry
|
10
|
+
end
|
11
|
+
# trust that the mysql jar is already present
|
12
|
+
end
|
13
|
+
require 'active_record/connection_adapters/jdbc_adapter'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_record/connection_adapters/jdbc_adapter'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
tried_gem = false
|
2
|
+
begin
|
3
|
+
require "jdbc/postgres"
|
4
|
+
rescue LoadError
|
5
|
+
unless tried_gem
|
6
|
+
require 'rubygems'
|
7
|
+
gem "jdbc-postgres"
|
8
|
+
tried_gem = true
|
9
|
+
retry
|
10
|
+
end
|
11
|
+
# trust that the postgres jar is already present
|
12
|
+
end
|
13
|
+
require 'active_record/connection_adapters/jdbc_adapter'
|
data/lib/jdbc_adapter.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
if RUBY_PLATFORM =~ /java/
|
2
|
+
begin
|
3
|
+
tried_gem ||= false
|
4
|
+
require 'active_record/version'
|
5
|
+
rescue LoadError
|
6
|
+
raise if tried_gem
|
7
|
+
require 'rubygems'
|
8
|
+
gem 'activerecord'
|
9
|
+
tried_gem = true
|
10
|
+
retry
|
11
|
+
end
|
12
|
+
if ActiveRecord::VERSION::MAJOR < 2
|
13
|
+
if defined?(RAILS_CONNECTION_ADAPTERS)
|
14
|
+
RAILS_CONNECTION_ADAPTERS << %q(jdbc)
|
15
|
+
else
|
16
|
+
RAILS_CONNECTION_ADAPTERS = %w(jdbc)
|
17
|
+
end
|
18
|
+
if ActiveRecord::VERSION::MAJOR == 1 && ActiveRecord::VERSION::MINOR == 14
|
19
|
+
require 'active_record/connection_adapters/jdbc_adapter'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
if defined?(RAILS_ROOT)
|
23
|
+
to_file = File.expand_path(File.join(RAILS_ROOT, 'lib', 'tasks', 'jdbc_databases.rake'))
|
24
|
+
from_file = File.expand_path(File.join(File.dirname(__FILE__), 'tasks', 'jdbc_databases.rake'))
|
25
|
+
if !File.exist?(to_file) || (File.mtime(to_file) < File.mtime(from_file))
|
26
|
+
require 'fileutils'
|
27
|
+
FileUtils.cp from_file, to_file, :verbose => true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
else
|
31
|
+
warn "ActiveRecord-JDBC is for use with JRuby only"
|
32
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module JdbcSpec
|
2
|
+
module DB2
|
3
|
+
def self.column_selector
|
4
|
+
[/db2/i, lambda {|cfg,col|
|
5
|
+
if cfg[:url] =~ /^jdbc:derby:net:/
|
6
|
+
col.extend(::JdbcSpec::Derby::Column)
|
7
|
+
else
|
8
|
+
col.extend(::JdbcSpec::DB2::Column)
|
9
|
+
end }]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.adapter_selector
|
13
|
+
[/db2/i, lambda {|cfg,adapt|
|
14
|
+
if cfg[:url] =~ /^jdbc:derby:net:/
|
15
|
+
adapt.extend(::JdbcSpec::Derby)
|
16
|
+
else
|
17
|
+
adapt.extend(::JdbcSpec::DB2)
|
18
|
+
end }]
|
19
|
+
end
|
20
|
+
|
21
|
+
module Column
|
22
|
+
def type_cast(value)
|
23
|
+
return nil if value.nil? || value =~ /^\s*null\s*$/i
|
24
|
+
case type
|
25
|
+
when :string then value
|
26
|
+
when :integer then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
27
|
+
when :primary_key then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
28
|
+
when :float then value.to_f
|
29
|
+
when :datetime then cast_to_date_or_time(value)
|
30
|
+
when :timestamp then cast_to_time(value)
|
31
|
+
when :time then cast_to_time(value)
|
32
|
+
else value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
def cast_to_date_or_time(value)
|
36
|
+
return value if value.is_a? Date
|
37
|
+
return nil if value.blank?
|
38
|
+
guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
|
39
|
+
end
|
40
|
+
|
41
|
+
def cast_to_time(value)
|
42
|
+
return value if value.is_a? Time
|
43
|
+
time_array = ParseDate.parsedate value
|
44
|
+
time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1;
|
45
|
+
Time.send(ActiveRecord::Base.default_timezone, *time_array) rescue nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def guess_date_or_time(value)
|
49
|
+
(value.hour == 0 and value.min == 0 and value.sec == 0) ?
|
50
|
+
Date.new(value.year, value.month, value.day) : value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def modify_types(tp)
|
55
|
+
tp[:primary_key] = 'int generated by default as identity (start with 42) primary key'
|
56
|
+
tp[:string][:limit] = 255
|
57
|
+
tp[:integer][:limit] = nil
|
58
|
+
tp[:boolean][:limit] = nil
|
59
|
+
tp
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_limit_offset!(sql, options)
|
63
|
+
if limit = options[:limit]
|
64
|
+
offset = options[:offset] || 0
|
65
|
+
sql.gsub!(/SELECT/i, 'SELECT B.* FROM (SELECT A.*, row_number() over () AS internal$rownum FROM (SELECT')
|
66
|
+
sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def quote_column_name(column_name)
|
71
|
+
column_name
|
72
|
+
end
|
73
|
+
|
74
|
+
def quote(value, column = nil) # :nodoc:
|
75
|
+
if column && column.type == :primary_key
|
76
|
+
return value.to_s
|
77
|
+
end
|
78
|
+
if column && column.type == :decimal && value
|
79
|
+
return value.to_s
|
80
|
+
end
|
81
|
+
case value
|
82
|
+
when String
|
83
|
+
if column && column.type == :binary
|
84
|
+
"BLOB('#{quote_string(value)}')"
|
85
|
+
else
|
86
|
+
"'#{quote_string(value)}'"
|
87
|
+
end
|
88
|
+
else super
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def quote_string(string)
|
93
|
+
string.gsub(/'/, "''") # ' (for ruby-mode)
|
94
|
+
end
|
95
|
+
|
96
|
+
def quoted_true
|
97
|
+
'1'
|
98
|
+
end
|
99
|
+
|
100
|
+
def quoted_false
|
101
|
+
'0'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,362 @@
|
|
1
|
+
require 'jdbc_adapter/missing_functionality_helper'
|
2
|
+
|
3
|
+
module ::JdbcSpec
|
4
|
+
module ActiveRecordExtensions
|
5
|
+
def derby_connection(config)
|
6
|
+
config[:url] ||= "jdbc:derby:#{config[:database]};create=true"
|
7
|
+
config[:driver] ||= "org.apache.derby.jdbc.EmbeddedDriver"
|
8
|
+
embedded_driver(config)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Derby
|
13
|
+
def self.column_selector
|
14
|
+
[/derby/i, lambda {|cfg,col| col.extend(::JdbcSpec::Derby::Column)}]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.adapter_selector
|
18
|
+
[/derby/i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::Derby)}]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.monkey_rails
|
22
|
+
unless @already_monkeyd
|
23
|
+
# Needed because Rails is broken wrt to quoting of
|
24
|
+
# some values. Most databases are nice about it,
|
25
|
+
# but not Derby. The real issue is that you can't
|
26
|
+
# compare a CHAR value to a NUMBER column.
|
27
|
+
::ActiveRecord::Associations::ClassMethods.module_eval do
|
28
|
+
private
|
29
|
+
|
30
|
+
def select_limited_ids_list(options, join_dependency)
|
31
|
+
connection.select_all(
|
32
|
+
construct_finder_sql_for_association_limiting(options, join_dependency),
|
33
|
+
"#{name} Load IDs For Limited Eager Loading"
|
34
|
+
).collect { |row| connection.quote(row[primary_key], columns_hash[primary_key]) }.join(", ")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
@already_monkeyd = true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.extended(*args)
|
43
|
+
monkey_rails
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.included(*args)
|
47
|
+
monkey_rails
|
48
|
+
end
|
49
|
+
|
50
|
+
module Column
|
51
|
+
def value_to_binary(value)
|
52
|
+
value.scan(/[0-9A-Fa-f]{2}/).collect {|v| v.to_i(16)}.pack("C*")
|
53
|
+
end
|
54
|
+
|
55
|
+
def cast_to_date_or_time(value)
|
56
|
+
return value if value.is_a? Date
|
57
|
+
return nil if value.blank?
|
58
|
+
guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
|
59
|
+
end
|
60
|
+
|
61
|
+
def cast_to_time(value)
|
62
|
+
return value if value.is_a? Time
|
63
|
+
time_array = ParseDate.parsedate value
|
64
|
+
time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1;
|
65
|
+
Time.send(ActiveRecord::Base.default_timezone, *time_array) rescue nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def guess_date_or_time(value)
|
69
|
+
(value.hour == 0 and value.min == 0 and value.sec == 0) ?
|
70
|
+
Date.new(value.year, value.month, value.day) : value
|
71
|
+
end
|
72
|
+
|
73
|
+
def simplified_type(field_type)
|
74
|
+
return :boolean if field_type =~ /smallint/i
|
75
|
+
return :float if field_type =~ /real/i
|
76
|
+
super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
include JdbcSpec::MissingFunctionalityHelper
|
81
|
+
|
82
|
+
def modify_types(tp)
|
83
|
+
tp[:primary_key] = "int generated by default as identity NOT NULL PRIMARY KEY"
|
84
|
+
tp[:integer][:limit] = nil
|
85
|
+
tp[:string][:limit] = 256
|
86
|
+
tp[:boolean] = {:name => "smallint"}
|
87
|
+
tp
|
88
|
+
end
|
89
|
+
|
90
|
+
def classes_for_table_name(table)
|
91
|
+
ActiveRecord::Base.send(:subclasses).select {|klass| klass.table_name == table}
|
92
|
+
end
|
93
|
+
|
94
|
+
# Set the sequence to the max value of the table's column.
|
95
|
+
def reset_sequence!(table, column, sequence = nil)
|
96
|
+
mpk = select_value("SELECT MAX(#{quote_column_name column}) FROM #{table}")
|
97
|
+
execute("ALTER TABLE #{table} ALTER COLUMN #{quote_column_name column} RESTART WITH #{mpk.to_i + 1}")
|
98
|
+
end
|
99
|
+
|
100
|
+
def reset_pk_sequence!(table, pk = nil, sequence = nil)
|
101
|
+
klasses = classes_for_table_name(table)
|
102
|
+
klass = klasses.nil? ? nil : klasses.first
|
103
|
+
pk = klass.primary_key unless klass.nil?
|
104
|
+
if pk && klass.columns_hash[pk].type == :integer
|
105
|
+
reset_sequence!(klass.table_name, pk)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def primary_key(table_name) #:nodoc:
|
110
|
+
primary_keys(table_name).first
|
111
|
+
end
|
112
|
+
|
113
|
+
def remove_index(table_name, options) #:nodoc:
|
114
|
+
execute "DROP INDEX #{index_name(table_name, options)}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def rename_table(name, new_name)
|
118
|
+
execute "RENAME TABLE #{name} TO #{new_name}"
|
119
|
+
end
|
120
|
+
|
121
|
+
COLUMN_INFO_STMT = "SELECT C.COLUMNNAME, C.REFERENCEID, C.COLUMNNUMBER FROM SYS.SYSCOLUMNS C, SYS.SYSTABLES T WHERE T.TABLEID = '%s' AND T.TABLEID = C.REFERENCEID ORDER BY C.COLUMNNUMBER"
|
122
|
+
|
123
|
+
COLUMN_TYPE_STMT = "SELECT COLUMNDATATYPE, COLUMNDEFAULT FROM SYS.SYSCOLUMNS WHERE REFERENCEID = '%s' AND COLUMNNAME = '%s'"
|
124
|
+
|
125
|
+
AUTO_INC_STMT = "SELECT AUTOINCREMENTSTART, AUTOINCREMENTINC, COLUMNNAME, REFERENCEID, COLUMNDEFAULT FROM SYS.SYSCOLUMNS WHERE REFERENCEID = '%s' AND COLUMNNAME = '%s'"
|
126
|
+
AUTO_INC_STMT2 = "SELECT AUTOINCREMENTSTART, AUTOINCREMENTINC, COLUMNNAME, REFERENCEID, COLUMNDEFAULT FROM SYS.SYSCOLUMNS WHERE REFERENCEID = (SELECT T.TABLEID FROM SYS.SYSTABLES T WHERE T.TABLENAME = '%s') AND COLUMNNAME = '%s'"
|
127
|
+
|
128
|
+
def add_quotes(name)
|
129
|
+
return name unless name
|
130
|
+
%Q{"#{name}"}
|
131
|
+
end
|
132
|
+
|
133
|
+
def strip_quotes(str)
|
134
|
+
return str unless str
|
135
|
+
return str unless /^(["']).*\1$/ =~ str
|
136
|
+
str[1..-2]
|
137
|
+
end
|
138
|
+
|
139
|
+
def expand_double_quotes(name)
|
140
|
+
return name unless name && name['"']
|
141
|
+
name.gsub(/"/,'""')
|
142
|
+
end
|
143
|
+
|
144
|
+
def reinstate_auto_increment(name, refid, coldef)
|
145
|
+
stmt = AUTO_INC_STMT % [refid, strip_quotes(name)]
|
146
|
+
data = execute(stmt).first
|
147
|
+
if data
|
148
|
+
start = data['autoincrementstart']
|
149
|
+
if start
|
150
|
+
coldef << " GENERATED " << (data['columndefault'].nil? ? "ALWAYS" : "BY DEFAULT ")
|
151
|
+
coldef << "AS IDENTITY (START WITH "
|
152
|
+
coldef << start
|
153
|
+
coldef << ", INCREMENT BY "
|
154
|
+
coldef << data['autoincrementinc']
|
155
|
+
coldef << ")"
|
156
|
+
return true
|
157
|
+
end
|
158
|
+
end
|
159
|
+
false
|
160
|
+
end
|
161
|
+
|
162
|
+
def reinstate_auto_increment(name, refid, coldef)
|
163
|
+
stmt = AUTO_INC_STMT % [refid, strip_quotes(name)]
|
164
|
+
data = execute(stmt).first
|
165
|
+
if data
|
166
|
+
start = data['autoincrementstart']
|
167
|
+
if start
|
168
|
+
coldef << " GENERATED " << (data['columndefault'].nil? ? "ALWAYS" : "BY DEFAULT ")
|
169
|
+
coldef << "AS IDENTITY (START WITH "
|
170
|
+
coldef << start
|
171
|
+
coldef << ", INCREMENT BY "
|
172
|
+
coldef << data['autoincrementinc']
|
173
|
+
coldef << ")"
|
174
|
+
return true
|
175
|
+
end
|
176
|
+
end
|
177
|
+
false
|
178
|
+
end
|
179
|
+
|
180
|
+
def auto_increment_stmt(tname, cname)
|
181
|
+
stmt = AUTO_INC_STMT2 % [tname, strip_quotes(cname)]
|
182
|
+
data = execute(stmt).first
|
183
|
+
if data
|
184
|
+
start = data['autoincrementstart']
|
185
|
+
if start
|
186
|
+
coldef = ""
|
187
|
+
coldef << " GENERATED " << (data['columndefault'].nil? ? "ALWAYS" : "BY DEFAULT ")
|
188
|
+
coldef << "AS IDENTITY (START WITH "
|
189
|
+
coldef << start
|
190
|
+
coldef << ", INCREMENT BY "
|
191
|
+
coldef << data['autoincrementinc']
|
192
|
+
coldef << ")"
|
193
|
+
return coldef
|
194
|
+
end
|
195
|
+
end
|
196
|
+
""
|
197
|
+
end
|
198
|
+
|
199
|
+
def create_column(name, refid, colno)
|
200
|
+
stmt = COLUMN_TYPE_STMT % [refid, strip_quotes(name)]
|
201
|
+
coldef = ""
|
202
|
+
data = execute(stmt).first
|
203
|
+
if data
|
204
|
+
coldef << add_quotes(expand_double_quotes(strip_quotes(name)))
|
205
|
+
coldef << " "
|
206
|
+
coldef << data['columndatatype']
|
207
|
+
if !reinstate_auto_increment(name, refid, coldef) && data['columndefault']
|
208
|
+
coldef << " DEFAULT " << data['columndefault']
|
209
|
+
end
|
210
|
+
end
|
211
|
+
coldef
|
212
|
+
end
|
213
|
+
|
214
|
+
SIZEABLE = %w(VARCHAR CLOB BLOB)
|
215
|
+
|
216
|
+
def structure_dump #:nodoc:
|
217
|
+
definition=""
|
218
|
+
rs = @connection.connection.meta_data.getTables(nil,nil,nil,["TABLE"].to_java(:string))
|
219
|
+
while rs.next
|
220
|
+
tname = rs.getString(3)
|
221
|
+
definition << "CREATE TABLE #{tname} (\n"
|
222
|
+
rs2 = @connection.connection.meta_data.getColumns(nil,nil,tname,nil)
|
223
|
+
first_col = true
|
224
|
+
while rs2.next
|
225
|
+
col_name = add_quotes(rs2.getString(4));
|
226
|
+
default = ""
|
227
|
+
d1 = rs2.getString(13)
|
228
|
+
if d1 =~ /^GENERATED_/
|
229
|
+
default = auto_increment_stmt(tname, col_name)
|
230
|
+
elsif d1
|
231
|
+
default = " DEFAULT #{d1}"
|
232
|
+
end
|
233
|
+
|
234
|
+
type = rs2.getString(6)
|
235
|
+
col_size = rs2.getString(7)
|
236
|
+
nulling = (rs2.getString(18) == 'NO' ? " NOT NULL" : "")
|
237
|
+
create_col_string = add_quotes(expand_double_quotes(strip_quotes(col_name))) +
|
238
|
+
" " +
|
239
|
+
type +
|
240
|
+
(SIZEABLE.include?(type) ? "(#{col_size})" : "") +
|
241
|
+
nulling +
|
242
|
+
default
|
243
|
+
if !first_col
|
244
|
+
create_col_string = ",\n #{create_col_string}"
|
245
|
+
else
|
246
|
+
create_col_string = " #{create_col_string}"
|
247
|
+
end
|
248
|
+
|
249
|
+
definition << create_col_string
|
250
|
+
|
251
|
+
first_col = false
|
252
|
+
end
|
253
|
+
definition << ");\n\n"
|
254
|
+
end
|
255
|
+
definition
|
256
|
+
end
|
257
|
+
|
258
|
+
# Support for removing columns added via derby bug issue:
|
259
|
+
# https://issues.apache.org/jira/browse/DERBY-1489
|
260
|
+
#
|
261
|
+
# This feature has not made it into a formal release and is not in Java 6.
|
262
|
+
# If the normal strategy fails we fall back on a strategy by creating a new
|
263
|
+
# table without the new column and there after moving the data to the new
|
264
|
+
#
|
265
|
+
def remove_column(table_name, column_name)
|
266
|
+
begin
|
267
|
+
execute "ALTER TABLE #{table_name} DROP COLUMN #{column_name} RESTRICT"
|
268
|
+
rescue
|
269
|
+
alter_table(table_name) do |definition|
|
270
|
+
definition.columns.delete(definition[column_name])
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
# Notes about changing in Derby:
|
276
|
+
# http://db.apache.org/derby/docs/10.2/ref/rrefsqlj81859.html#rrefsqlj81859__rrefsqlj37860)
|
277
|
+
#
|
278
|
+
# We support changing columns using the strategy outlined in:
|
279
|
+
# https://issues.apache.org/jira/browse/DERBY-1515
|
280
|
+
#
|
281
|
+
# This feature has not made it into a formal release and is not in Java 6. We will
|
282
|
+
# need to conditionally support this somehow (supposed to arrive for 10.3.0.0)
|
283
|
+
def change_column(table_name, column_name, type, options = {})
|
284
|
+
# null/not nulling is easy, handle that separately
|
285
|
+
if options.include?(:null)
|
286
|
+
# This seems to only work with 10.2 of Derby
|
287
|
+
if options.delete(:null) == false
|
288
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} NOT NULL"
|
289
|
+
else
|
290
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} NULL"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
# anything left to do?
|
295
|
+
unless options.empty?
|
296
|
+
begin
|
297
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DATA TYPE #{type_to_sql(type, options[:limit])}"
|
298
|
+
rescue
|
299
|
+
transaction do
|
300
|
+
temp_new_column_name = "#{column_name}_newtype"
|
301
|
+
# 1) ALTER TABLE t ADD COLUMN c1_newtype NEWTYPE;
|
302
|
+
add_column table_name, temp_new_column_name, type, options
|
303
|
+
# 2) UPDATE t SET c1_newtype = c1;
|
304
|
+
execute "UPDATE #{table_name} SET #{temp_new_column_name} = CAST(#{column_name} AS #{type_to_sql(type, options[:limit])})"
|
305
|
+
# 3) ALTER TABLE t DROP COLUMN c1;
|
306
|
+
remove_column table_name, column_name
|
307
|
+
# 4) ALTER TABLE t RENAME COLUMN c1_newtype to c1;
|
308
|
+
rename_column table_name, temp_new_column_name, column_name
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
# Support for renaming columns:
|
315
|
+
# https://issues.apache.org/jira/browse/DERBY-1490
|
316
|
+
#
|
317
|
+
# This feature is expect to arrive in version 10.3.0.0:
|
318
|
+
# http://wiki.apache.org/db-derby/DerbyTenThreeRelease)
|
319
|
+
#
|
320
|
+
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
321
|
+
begin
|
322
|
+
execute "ALTER TABLE #{table_name} ALTER RENAME COLUMN #{column_name} TO #{new_column_name}"
|
323
|
+
rescue
|
324
|
+
alter_table(table_name, :rename => {column_name => new_column_name})
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def primary_keys(table_name)
|
329
|
+
@connection.primary_keys table_name.to_s.upcase
|
330
|
+
end
|
331
|
+
|
332
|
+
def recreate_database(db_name)
|
333
|
+
tables.each do |t|
|
334
|
+
drop_table t
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
# For DDL it appears you can quote "" column names, but in queries (like insert it errors out?)
|
339
|
+
def quote_column_name(name) #:nodoc:
|
340
|
+
if /^references$/i =~ name
|
341
|
+
%Q{"#{name.upcase}"}
|
342
|
+
elsif /[A-Z]/ =~ name && /[a-z]/ =~ name
|
343
|
+
%Q{"#{name}"}
|
344
|
+
elsif name =~ /\s/
|
345
|
+
%Q{"#{name.upcase}"}
|
346
|
+
elsif name =~ /^[_\d]/
|
347
|
+
%Q{"#{name.upcase}"}
|
348
|
+
else
|
349
|
+
name
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def quoted_true
|
354
|
+
'1'
|
355
|
+
end
|
356
|
+
|
357
|
+
def quoted_false
|
358
|
+
'0'
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|