activerecord-jdbc-adapter 0.9.3-java
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 +248 -0
- data/LICENSE.txt +21 -0
- data/Manifest.txt +125 -0
- data/README.txt +218 -0
- data/Rakefile +10 -0
- data/lib/active_record/connection_adapters/cachedb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/derby_adapter.rb +13 -0
- data/lib/active_record/connection_adapters/h2_adapter.rb +13 -0
- data/lib/active_record/connection_adapters/hsqldb_adapter.rb +13 -0
- data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +640 -0
- data/lib/active_record/connection_adapters/jdbc_adapter_spec.rb +26 -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/active_record/connection_adapters/sqlite3_adapter.rb +13 -0
- data/lib/generators/jdbc/jdbc_generator.rb +9 -0
- data/lib/jdbc_adapter.rb +27 -0
- data/lib/jdbc_adapter/jdbc.rake +121 -0
- data/lib/jdbc_adapter/jdbc_adapter_internal.jar +0 -0
- data/lib/jdbc_adapter/jdbc_cachedb.rb +33 -0
- data/lib/jdbc_adapter/jdbc_db2.rb +203 -0
- data/lib/jdbc_adapter/jdbc_derby.rb +430 -0
- data/lib/jdbc_adapter/jdbc_firebird.rb +109 -0
- data/lib/jdbc_adapter/jdbc_hsqldb.rb +218 -0
- data/lib/jdbc_adapter/jdbc_informix.rb +147 -0
- data/lib/jdbc_adapter/jdbc_mimer.rb +141 -0
- data/lib/jdbc_adapter/jdbc_mssql.rb +337 -0
- data/lib/jdbc_adapter/jdbc_mysql.rb +236 -0
- data/lib/jdbc_adapter/jdbc_oracle.rb +377 -0
- data/lib/jdbc_adapter/jdbc_postgre.rb +498 -0
- data/lib/jdbc_adapter/jdbc_sqlite3.rb +384 -0
- data/lib/jdbc_adapter/jdbc_sybase.rb +50 -0
- data/lib/jdbc_adapter/missing_functionality_helper.rb +87 -0
- data/lib/jdbc_adapter/rake_tasks.rb +10 -0
- data/lib/jdbc_adapter/tsql_helper.rb +60 -0
- data/lib/jdbc_adapter/version.rb +5 -0
- data/lib/pg.rb +4 -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/compile.rake +23 -0
- data/rakelib/package.rake +90 -0
- data/rakelib/rails.rake +41 -0
- data/rakelib/test.rake +76 -0
- data/src/java/jdbc_adapter/JdbcAdapterInternalService.java +53 -0
- data/src/java/jdbc_adapter/JdbcConnectionFactory.java +36 -0
- data/src/java/jdbc_adapter/JdbcDerbySpec.java +293 -0
- data/src/java/jdbc_adapter/JdbcMySQLSpec.java +134 -0
- data/src/java/jdbc_adapter/MssqlRubyJdbcConnection.java +71 -0
- data/src/java/jdbc_adapter/PostgresRubyJdbcConnection.java +55 -0
- data/src/java/jdbc_adapter/RubyJdbcConnection.java +1162 -0
- data/src/java/jdbc_adapter/SQLBlock.java +27 -0
- data/src/java/jdbc_adapter/Sqlite3RubyJdbcConnection.java +41 -0
- data/test/abstract_db_create.rb +107 -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/cachedb_simple_test.rb +6 -0
- data/test/db/cachedb.rb +9 -0
- data/test/db/db2.rb +9 -0
- data/test/db/derby.rb +14 -0
- data/test/db/h2.rb +11 -0
- data/test/db/hsqldb.rb +12 -0
- data/test/db/informix.rb +11 -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/mssql.rb +9 -0
- data/test/db/mysql.rb +10 -0
- data/test/db/oracle.rb +34 -0
- data/test/db/postgres.rb +9 -0
- data/test/db/sqlite3.rb +15 -0
- data/test/db2_simple_test.rb +10 -0
- data/test/derby_migration_test.rb +21 -0
- data/test/derby_multibyte_test.rb +12 -0
- data/test/derby_simple_test.rb +21 -0
- data/test/generic_jdbc_connection_test.rb +9 -0
- data/test/h2_simple_test.rb +6 -0
- data/test/has_many_through.rb +79 -0
- data/test/helper.rb +5 -0
- data/test/hsqldb_simple_test.rb +6 -0
- data/test/informix_simple_test.rb +48 -0
- data/test/jdbc_adapter/jdbc_db2_test.rb +26 -0
- data/test/jdbc_adapter/jdbc_sybase_test.rb +33 -0
- data/test/jdbc_common.rb +25 -0
- data/test/jndi_callbacks_test.rb +38 -0
- data/test/jndi_test.rb +35 -0
- data/test/manualTestDatabase.rb +191 -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/add_not_null_column_to_table.rb +12 -0
- data/test/models/auto_id.rb +18 -0
- data/test/models/data_types.rb +28 -0
- data/test/models/entry.rb +23 -0
- data/test/models/mixed_case.rb +20 -0
- data/test/models/reserved_word.rb +18 -0
- data/test/models/string_id.rb +18 -0
- data/test/models/validates_uniqueness_of_string.rb +19 -0
- data/test/mssql_simple_test.rb +6 -0
- data/test/mysql_db_create_test.rb +25 -0
- data/test/mysql_multibyte_test.rb +10 -0
- data/test/mysql_nonstandard_primary_key_test.rb +42 -0
- data/test/mysql_simple_test.rb +32 -0
- data/test/oracle_simple_test.rb +29 -0
- data/test/pick_rails_version.rb +3 -0
- data/test/postgres_db_create_test.rb +21 -0
- data/test/postgres_mixed_case_test.rb +19 -0
- data/test/postgres_nonseq_pkey_test.rb +40 -0
- data/test/postgres_reserved_test.rb +22 -0
- data/test/postgres_schema_search_path_test.rb +46 -0
- data/test/postgres_simple_test.rb +13 -0
- data/test/simple.rb +475 -0
- data/test/sqlite3_simple_test.rb +233 -0
- data/test/sybase_jtds_simple_test.rb +6 -0
- metadata +188 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
module ::JdbcSpec
|
|
2
|
+
module ActiveRecordExtensions
|
|
3
|
+
def hsqldb_connection(config)
|
|
4
|
+
require File.dirname(__FILE__) + "/../active_record/connection_adapters/hsqldb_adapter"
|
|
5
|
+
config[:url] ||= "jdbc:hsqldb:#{config[:database]}"
|
|
6
|
+
config[:driver] ||= "org.hsqldb.jdbcDriver"
|
|
7
|
+
embedded_driver(config)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def h2_connection(config)
|
|
11
|
+
require File.dirname(__FILE__) + "/../active_record/connection_adapters/h2_adapter"
|
|
12
|
+
config[:url] ||= "jdbc:h2:#{config[:database]}"
|
|
13
|
+
config[:driver] ||= "org.h2.Driver"
|
|
14
|
+
embedded_driver(config)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module HSQLDB
|
|
19
|
+
def self.extended(mod)
|
|
20
|
+
mod.class.class_eval do
|
|
21
|
+
alias_chained_method :insert, :query_dirty, :insert
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.adapter_matcher(name, *)
|
|
26
|
+
name =~ /hsqldb/i ? self : false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.column_selector
|
|
30
|
+
[/hsqldb|\.h2\./i, lambda {|cfg,col| col.extend(::JdbcSpec::HSQLDB::Column)}]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module Column
|
|
34
|
+
private
|
|
35
|
+
def simplified_type(field_type)
|
|
36
|
+
case field_type
|
|
37
|
+
when /longvarchar/i
|
|
38
|
+
:text
|
|
39
|
+
when /tinyint/i
|
|
40
|
+
:boolean
|
|
41
|
+
else
|
|
42
|
+
super(field_type)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Override of ActiveRecord::ConnectionAdapters::Column
|
|
47
|
+
def extract_limit(sql_type)
|
|
48
|
+
# HSQLDB appears to return "LONGVARCHAR(0)" for :text columns, which
|
|
49
|
+
# for AR purposes should be interpreted as "no limit"
|
|
50
|
+
return nil if sql_type =~ /\(0\)/
|
|
51
|
+
super
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Post process default value from JDBC into a Rails-friendly format (columns{-internal})
|
|
55
|
+
def default_value(value)
|
|
56
|
+
# jdbc returns column default strings with actual single quotes around the value.
|
|
57
|
+
return $1 if value =~ /^'(.*)'$/
|
|
58
|
+
|
|
59
|
+
value
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def adapter_name #:nodoc:
|
|
64
|
+
defined?(::Jdbc::H2) ? 'h2' : 'hsqldb'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def modify_types(tp)
|
|
68
|
+
tp[:primary_key] = "INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY"
|
|
69
|
+
tp[:integer][:limit] = nil
|
|
70
|
+
tp[:boolean][:limit] = nil
|
|
71
|
+
# set text and float limits so we don't see odd scales tacked on
|
|
72
|
+
# in migrations
|
|
73
|
+
tp[:boolean] = { :name => "tinyint" }
|
|
74
|
+
tp[:text][:limit] = nil
|
|
75
|
+
tp[:float][:limit] = 17 if defined?(::Jdbc::H2)
|
|
76
|
+
tp[:string][:limit] = 255
|
|
77
|
+
tp[:datetime] = { :name => "DATETIME" }
|
|
78
|
+
tp[:timestamp] = { :name => "DATETIME" }
|
|
79
|
+
tp[:time] = { :name => "TIME" }
|
|
80
|
+
tp[:date] = { :name => "DATE" }
|
|
81
|
+
tp
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def quote(value, column = nil) # :nodoc:
|
|
85
|
+
return value.quoted_id if value.respond_to?(:quoted_id)
|
|
86
|
+
|
|
87
|
+
case value
|
|
88
|
+
when String
|
|
89
|
+
if respond_to?(:h2_adapter) && value.empty?
|
|
90
|
+
"''"
|
|
91
|
+
elsif column && column.type == :binary
|
|
92
|
+
"'#{value.unpack("H*")}'"
|
|
93
|
+
elsif column.respond_to?(:primary) && column.primary && column.klass != String
|
|
94
|
+
value.to_i.to_s
|
|
95
|
+
else
|
|
96
|
+
"'#{quote_string(value)}'"
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
super
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def quote_column_name(name) #:nodoc:
|
|
104
|
+
name = name.to_s
|
|
105
|
+
if name =~ /[-]/
|
|
106
|
+
%Q{"#{name.upcase}"}
|
|
107
|
+
else
|
|
108
|
+
name
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def quote_string(str)
|
|
113
|
+
str.gsub(/'/, "''")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def quoted_true
|
|
117
|
+
'1'
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def quoted_false
|
|
121
|
+
'0'
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def add_column(table_name, column_name, type, options = {})
|
|
125
|
+
if option_not_null = options[:null] == false
|
|
126
|
+
option_not_null = options.delete(:null)
|
|
127
|
+
end
|
|
128
|
+
add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
|
|
129
|
+
add_column_options!(add_column_sql, options)
|
|
130
|
+
execute(add_column_sql)
|
|
131
|
+
if option_not_null
|
|
132
|
+
alter_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} NOT NULL"
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
|
137
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} #{type_to_sql(type, options[:limit])}"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def change_column_default(table_name, column_name, default) #:nodoc:
|
|
141
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DEFAULT #{quote(default)}"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
|
145
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} RENAME TO #{new_column_name}"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Maps logical Rails types to MySQL-specific data types.
|
|
149
|
+
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
|
150
|
+
return super if defined?(::Jdbc::H2) || type.to_s != 'integer' || limit == nil
|
|
151
|
+
|
|
152
|
+
type
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def rename_table(name, new_name)
|
|
156
|
+
execute "ALTER TABLE #{name} RENAME TO #{new_name}"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
|
|
160
|
+
log(sql,name) do
|
|
161
|
+
@connection.execute_update(sql)
|
|
162
|
+
end
|
|
163
|
+
table = sql.split(" ", 4)[2]
|
|
164
|
+
id_value || last_insert_id(table, nil)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def last_insert_id(table, sequence_name)
|
|
168
|
+
Integer(select_value("CALL IDENTITY()"))
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Override normal #_execute: See Rubyforge #11567
|
|
172
|
+
def _execute(sql, name = nil)
|
|
173
|
+
if ::ActiveRecord::ConnectionAdapters::JdbcConnection::select?(sql)
|
|
174
|
+
@connection.execute_query(sql)
|
|
175
|
+
elsif ::ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql)
|
|
176
|
+
insert(sql, name)
|
|
177
|
+
else
|
|
178
|
+
@connection.execute_update(sql)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def add_limit_offset!(sql, options) #:nodoc:
|
|
183
|
+
offset = options[:offset] || 0
|
|
184
|
+
bef = sql[7..-1]
|
|
185
|
+
if limit = options[:limit]
|
|
186
|
+
sql.replace "select limit #{offset} #{limit} #{bef}"
|
|
187
|
+
elsif offset > 0
|
|
188
|
+
sql.replace "select limit #{offset} 0 #{bef}"
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# override to filter out system tables that otherwise end
|
|
193
|
+
# up in db/schema.rb during migrations. JdbcConnection#tables
|
|
194
|
+
# now takes an optional block filter so we can screen out
|
|
195
|
+
# rows corresponding to system tables. HSQLDB names its
|
|
196
|
+
# system tables SYSTEM.*, but H2 seems to name them without
|
|
197
|
+
# any kind of convention
|
|
198
|
+
def tables
|
|
199
|
+
@connection.tables.select {|row| row.to_s !~ /^system_/i }
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def remove_index(table_name, options = {})
|
|
203
|
+
execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
module H2
|
|
208
|
+
include HSQLDB
|
|
209
|
+
|
|
210
|
+
def self.adapter_matcher(name, *)
|
|
211
|
+
name =~ /\.h2\./i ? self : false
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def h2_adapter
|
|
215
|
+
true
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
module ::ActiveRecord
|
|
2
|
+
class Base
|
|
3
|
+
after_save :write_lobs
|
|
4
|
+
|
|
5
|
+
private
|
|
6
|
+
def write_lobs
|
|
7
|
+
if connection.is_a?(JdbcSpec::Informix)
|
|
8
|
+
self.class.columns.each do |c|
|
|
9
|
+
if [:text, :binary].include? c.type
|
|
10
|
+
value = self[c.name]
|
|
11
|
+
value = value.to_yaml if unserializable_attribute?(c.name, c)
|
|
12
|
+
|
|
13
|
+
unless value.nil? || (value == '')
|
|
14
|
+
connection.write_large_object(c.type == :binary,
|
|
15
|
+
c.name,
|
|
16
|
+
self.class.table_name,
|
|
17
|
+
self.class.primary_key,
|
|
18
|
+
quote_value(id),
|
|
19
|
+
value)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module ::JdbcSpec
|
|
29
|
+
module ActiveRecordExtensions
|
|
30
|
+
def informix_connection(config)
|
|
31
|
+
config[:port] ||= 9088
|
|
32
|
+
config[:url] ||= "jdbc:informix-sqli://#{config[:host]}:#{config[:port]}/#{config[:database]}:INFORMIXSERVER=#{config[:servername]}"
|
|
33
|
+
config[:driver] = 'com.informix.jdbc.IfxDriver'
|
|
34
|
+
jdbc_connection(config)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
module Informix
|
|
39
|
+
def self.extended(base)
|
|
40
|
+
@@db_major_version = base.select_one("SELECT dbinfo('version', 'major') version FROM systables WHERE tabid = 1")['version'].to_i
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.adapter_matcher(name, *)
|
|
44
|
+
name =~ /informix/i ? self : false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.column_selector
|
|
48
|
+
[ /informix/i,
|
|
49
|
+
lambda { |cfg, column| column.extend(::JdbcSpec::Informix::Column) } ]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
module Column
|
|
53
|
+
private
|
|
54
|
+
# TODO: Test all Informix column types.
|
|
55
|
+
def simplified_type(field_type)
|
|
56
|
+
if field_type =~ /serial/i
|
|
57
|
+
:primary_key
|
|
58
|
+
else
|
|
59
|
+
super
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def modify_types(tp)
|
|
65
|
+
tp[:primary_key] = "SERIAL PRIMARY KEY"
|
|
66
|
+
tp[:string] = { :name => "VARCHAR", :limit => 255 }
|
|
67
|
+
tp[:integer] = { :name => "INTEGER" }
|
|
68
|
+
tp[:float] = { :name => "FLOAT" }
|
|
69
|
+
tp[:decimal] = { :name => "DECIMAL" }
|
|
70
|
+
tp[:datetime] = { :name => "DATETIME YEAR TO FRACTION(5)" }
|
|
71
|
+
tp[:timestamp] = { :name => "DATETIME YEAR TO FRACTION(5)" }
|
|
72
|
+
tp[:time] = { :name => "DATETIME HOUR TO FRACTION(5)" }
|
|
73
|
+
tp[:date] = { :name => "DATE" }
|
|
74
|
+
tp[:binary] = { :name => "BYTE" }
|
|
75
|
+
tp[:boolean] = { :name => "BOOLEAN" }
|
|
76
|
+
tp
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def prefetch_primary_key?(table_name = nil)
|
|
80
|
+
true
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def supports_migrations?
|
|
84
|
+
true
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def default_sequence_name(table, column)
|
|
88
|
+
"#{table}_seq"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def add_limit_offset!(sql, options)
|
|
92
|
+
if options[:limit]
|
|
93
|
+
limit = "FIRST #{options[:limit]}"
|
|
94
|
+
# SKIP available only in IDS >= 10
|
|
95
|
+
offset = (@@db_major_version >= 10 && options[:offset]?
|
|
96
|
+
"SKIP #{options[:offset]}" : "")
|
|
97
|
+
sql.sub!(/^select /i, "SELECT #{offset} #{limit} ")
|
|
98
|
+
end
|
|
99
|
+
sql
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def next_sequence_value(sequence_name)
|
|
103
|
+
select_one("SELECT #{sequence_name}.nextval id FROM systables WHERE tabid=1")['id']
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# TODO: Add some smart quoting for newlines in string and text fields.
|
|
107
|
+
def quote_string(string)
|
|
108
|
+
string.gsub(/\'/, "''")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def quote(value, column = nil)
|
|
112
|
+
if column && [:binary, :text].include?(column.type)
|
|
113
|
+
# LOBs are updated separately by an after_save trigger.
|
|
114
|
+
"NULL"
|
|
115
|
+
elsif column && column.type == :date
|
|
116
|
+
"'#{value.mon}/#{value.day}/#{value.year}'"
|
|
117
|
+
else
|
|
118
|
+
super
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def create_table(name, options = {})
|
|
123
|
+
super(name, options)
|
|
124
|
+
execute("CREATE SEQUENCE #{name}_seq")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def rename_table(name, new_name)
|
|
128
|
+
execute("RENAME TABLE #{name} TO #{new_name}")
|
|
129
|
+
execute("RENAME SEQUENCE #{name}_seq TO #{new_name}_seq")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def drop_table(name)
|
|
133
|
+
super(name)
|
|
134
|
+
execute("DROP SEQUENCE #{name}_seq")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def remove_index(table_name, options = {})
|
|
138
|
+
@connection.execute_update("DROP INDEX #{index_name(table_name, options)}")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
private
|
|
142
|
+
def select(sql, name = nil)
|
|
143
|
+
# Informix does not like "= NULL", "!= NULL", or "<> NULL".
|
|
144
|
+
execute(sql.gsub(/(!=|<>)\s*null/i, "IS NOT NULL").gsub(/=\s*null/i, "IS NULL"), name)
|
|
145
|
+
end
|
|
146
|
+
end # module Informix
|
|
147
|
+
end # module ::JdbcSpec
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
module JdbcSpec
|
|
2
|
+
module Mimer
|
|
3
|
+
def self.adapter_matcher(name, *)
|
|
4
|
+
name =~ /mimer/i ? self : false
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def modify_types(tp)
|
|
8
|
+
tp[:primary_key] = "INTEGER NOT NULL PRIMARY KEY"
|
|
9
|
+
tp[:boolean][:limit] = nil
|
|
10
|
+
tp[:string][:limit] = 255
|
|
11
|
+
tp[:binary] = {:name => "BINARY VARYING", :limit => 4096}
|
|
12
|
+
tp[:text] = {:name => "VARCHAR", :limit => 4096}
|
|
13
|
+
tp[:datetime] = { :name => "TIMESTAMP" }
|
|
14
|
+
tp[:timestamp] = { :name => "TIMESTAMP" }
|
|
15
|
+
tp[:time] = { :name => "TIMESTAMP" }
|
|
16
|
+
tp[:date] = { :name => "TIMESTAMP" }
|
|
17
|
+
tp
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def default_sequence_name(table, column) #:nodoc:
|
|
21
|
+
"#{table}_seq"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def create_table(name, options = {}) #:nodoc:
|
|
25
|
+
super(name, options)
|
|
26
|
+
execute "CREATE SEQUENCE #{name}_seq" unless options[:id] == false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def drop_table(name, options = {}) #:nodoc:
|
|
30
|
+
super(name) rescue nil
|
|
31
|
+
execute "DROP SEQUENCE #{name}_seq" rescue nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
|
35
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} #{type_to_sql(type, options[:limit])}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def change_column_default(table_name, column_name, default) #:nodoc:
|
|
39
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DEFAULT #{quote(default)}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def remove_index(table_name, options = {}) #:nodoc:
|
|
43
|
+
execute "DROP INDEX #{index_name(table_name, options)}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
|
|
47
|
+
if pk.nil? # Who called us? What does the sql look like? No idea!
|
|
48
|
+
execute sql, name
|
|
49
|
+
elsif id_value # Pre-assigned id
|
|
50
|
+
log(sql, name) { @connection.execute_insert sql,pk }
|
|
51
|
+
else # Assume the sql contains a bind-variable for the id
|
|
52
|
+
id_value = select_one("SELECT NEXT_VALUE OF #{sequence_name} AS val FROM MIMER.ONEROW")['val']
|
|
53
|
+
log(sql, name) {
|
|
54
|
+
execute_prepared_insert(sql,id_value)
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
id_value
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def execute_prepared_insert(sql, id)
|
|
61
|
+
@stmts ||= {}
|
|
62
|
+
@stmts[sql] ||= @connection.ps(sql)
|
|
63
|
+
stmt = @stmts[sql]
|
|
64
|
+
stmt.setLong(1,id)
|
|
65
|
+
stmt.executeUpdate
|
|
66
|
+
id
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def quote(value, column = nil) #:nodoc:
|
|
70
|
+
return value.quoted_id if value.respond_to?(:quoted_id)
|
|
71
|
+
|
|
72
|
+
if String === value && column && column.type == :binary
|
|
73
|
+
return "X'#{quote_string(value.unpack("C*").collect {|v| v.to_s(16)}.join)}'"
|
|
74
|
+
end
|
|
75
|
+
case value
|
|
76
|
+
when String
|
|
77
|
+
%Q{'#{quote_string(value)}'}
|
|
78
|
+
when NilClass
|
|
79
|
+
'NULL'
|
|
80
|
+
when TrueClass
|
|
81
|
+
'1'
|
|
82
|
+
when FalseClass
|
|
83
|
+
'0'
|
|
84
|
+
when Numeric
|
|
85
|
+
value.to_s
|
|
86
|
+
when Date, Time
|
|
87
|
+
%Q{TIMESTAMP '#{value.strftime("%Y-%m-%d %H:%M:%S")}'}
|
|
88
|
+
else
|
|
89
|
+
%Q{'#{quote_string(value.to_yaml)}'}
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def quoted_true
|
|
94
|
+
'1'
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def quoted_false
|
|
98
|
+
'0'
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def add_limit_offset!(sql, options) # :nodoc:
|
|
102
|
+
@limit = options[:limit]
|
|
103
|
+
@offset = options[:offset]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def select_all(sql, name = nil)
|
|
107
|
+
@offset ||= 0
|
|
108
|
+
if !@limit || @limit == -1
|
|
109
|
+
range = @offset..-1
|
|
110
|
+
else
|
|
111
|
+
range = @offset...(@offset+@limit)
|
|
112
|
+
end
|
|
113
|
+
select(sql, name)[range]
|
|
114
|
+
ensure
|
|
115
|
+
@limit = @offset = nil
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def select_one(sql, name = nil)
|
|
119
|
+
@offset ||= 0
|
|
120
|
+
select(sql, name)[@offset]
|
|
121
|
+
ensure
|
|
122
|
+
@limit = @offset = nil
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def _execute(sql, name = nil)
|
|
126
|
+
if sql =~ /^select/i
|
|
127
|
+
@offset ||= 0
|
|
128
|
+
if !@limit || @limit == -1
|
|
129
|
+
range = @offset..-1
|
|
130
|
+
else
|
|
131
|
+
range = @offset...(@offset+@limit)
|
|
132
|
+
end
|
|
133
|
+
@connection.execute_query(sql)[range]
|
|
134
|
+
else
|
|
135
|
+
@connection.execute_update(sql)
|
|
136
|
+
end
|
|
137
|
+
ensure
|
|
138
|
+
@limit = @offset = nil
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|