activerecord-jdbc-adapter 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +33 -0
- data/Manifest.txt +17 -0
- data/README.txt +48 -20
- data/Rakefile +2 -169
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +11 -5
- data/lib/active_record/connection_adapters/jdbc_adapter_spec.rb +12 -0
- data/lib/jdbc_adapter.rb +1 -1
- data/lib/jdbc_adapter/jdbc.rake +43 -30
- data/lib/jdbc_adapter/jdbc_adapter_internal.jar +0 -0
- data/lib/jdbc_adapter/jdbc_db2.rb +2 -2
- data/lib/jdbc_adapter/jdbc_derby.rb +11 -0
- data/lib/jdbc_adapter/jdbc_hsqldb.rb +6 -1
- data/lib/jdbc_adapter/jdbc_mimer.rb +14 -7
- data/lib/jdbc_adapter/jdbc_mssql.rb +18 -2
- data/lib/jdbc_adapter/jdbc_mysql.rb +3 -0
- data/lib/jdbc_adapter/jdbc_oracle.rb +24 -14
- data/lib/jdbc_adapter/jdbc_postgre.rb +38 -18
- data/lib/jdbc_adapter/jdbc_sqlite3.rb +96 -26
- data/lib/jdbc_adapter/missing_functionality_helper.rb +40 -34
- data/lib/jdbc_adapter/rake_tasks.rb +1 -1
- data/lib/jdbc_adapter/tsql_helper.rb +1 -0
- data/lib/jdbc_adapter/version.rb +1 -1
- data/lib/pg.rb +4 -0
- data/rails_generators/jdbc_generator.rb +15 -0
- data/rails_generators/templates/jdbc.rake +8 -0
- data/rails_generators/templates/jdbc.rb +7 -0
- data/rakelib/compile.rake +23 -0
- data/rakelib/package.rake +85 -0
- data/rakelib/rails.rake +41 -0
- data/rakelib/test.rake +71 -0
- data/src/java/jdbc_adapter/JdbcAdapterInternalService.java +1 -0
- data/src/java/jdbc_adapter/JdbcDerbySpec.java +11 -46
- data/src/java/jdbc_adapter/JdbcMySQLSpec.java +3 -2
- data/src/java/jdbc_adapter/MssqlRubyJdbcConnection.java +71 -0
- data/src/java/jdbc_adapter/PostgresRubyJdbcConnection.java +24 -4
- data/src/java/jdbc_adapter/RubyJdbcConnection.java +57 -44
- data/test/abstract_db_create.rb +45 -0
- data/test/db/mysql.rb +2 -2
- data/test/db/postgres.rb +2 -2
- data/test/helper.rb +5 -0
- data/test/jdbc_adapter/jdbc_db2_test.rb +5 -0
- data/test/jdbc_common.rb +2 -0
- data/test/models/entry.rb +3 -0
- data/test/models/validates_uniqueness_of_string.rb +19 -0
- data/test/mysql_db_create_test.rb +25 -0
- data/test/mysql_nonstandard_primary_key_test.rb +42 -0
- data/test/mysql_simple_test.rb +5 -0
- data/test/postgres_db_create_test.rb +21 -0
- data/test/postgres_nonseq_pkey_test.rb +40 -0
- data/test/simple.rb +62 -1
- data/test/sqlite3_simple_test.rb +153 -10
- metadata +26 -5
Binary file
|
@@ -2,7 +2,7 @@ module JdbcSpec
|
|
2
2
|
module DB2
|
3
3
|
def self.adapter_matcher(name, config)
|
4
4
|
if name =~ /db2/i
|
5
|
-
return
|
5
|
+
return config[:url] =~ /^jdbc:derby:net:/ ? ::JdbcSpec::Derby : self
|
6
6
|
end
|
7
7
|
false
|
8
8
|
end
|
@@ -50,7 +50,7 @@ module JdbcSpec
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def modify_types(tp)
|
53
|
-
tp[:primary_key] = 'int generated by default as identity (start with
|
53
|
+
tp[:primary_key] = 'int not null generated by default as identity (start with 1) primary key'
|
54
54
|
tp[:string][:limit] = 255
|
55
55
|
tp[:integer][:limit] = nil
|
56
56
|
tp[:boolean][:limit] = nil
|
@@ -3,6 +3,7 @@ require 'jdbc_adapter/missing_functionality_helper'
|
|
3
3
|
module ::JdbcSpec
|
4
4
|
module ActiveRecordExtensions
|
5
5
|
def derby_connection(config)
|
6
|
+
require File.dirname(__FILE__) + "/../active_record/connection_adapters/derby_adapter"
|
6
7
|
config[:url] ||= "jdbc:derby:#{config[:database]};create=true"
|
7
8
|
config[:driver] ||= "org.apache.derby.jdbc.EmbeddedDriver"
|
8
9
|
embedded_driver(config)
|
@@ -400,6 +401,16 @@ module ::JdbcSpec
|
|
400
401
|
'0'
|
401
402
|
end
|
402
403
|
|
404
|
+
def add_limit_offset!(sql, options) #:nodoc:
|
405
|
+
if options[:offset]
|
406
|
+
sql << " OFFSET #{options[:offset]} ROWS"
|
407
|
+
end
|
408
|
+
if options[:limit]
|
409
|
+
#ROWS/ROW and FIRST/NEXT mean the same
|
410
|
+
sql << " FETCH FIRST #{options[:limit]} ROWS ONLY"
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
403
414
|
private
|
404
415
|
# Derby appears to define schemas using the username
|
405
416
|
def derby_schema
|
@@ -1,12 +1,14 @@
|
|
1
1
|
module ::JdbcSpec
|
2
2
|
module ActiveRecordExtensions
|
3
3
|
def hsqldb_connection(config)
|
4
|
+
require File.dirname(__FILE__) + "/../active_record/connection_adapters/hsqldb_adapter"
|
4
5
|
config[:url] ||= "jdbc:hsqldb:#{config[:database]}"
|
5
6
|
config[:driver] ||= "org.hsqldb.jdbcDriver"
|
6
7
|
embedded_driver(config)
|
7
8
|
end
|
8
9
|
|
9
10
|
def h2_connection(config)
|
11
|
+
require File.dirname(__FILE__) + "/../active_record/connection_adapters/h2_adapter"
|
10
12
|
config[:url] ||= "jdbc:h2:#{config[:database]}"
|
11
13
|
config[:driver] ||= "org.h2.Driver"
|
12
14
|
embedded_driver(config)
|
@@ -82,10 +84,13 @@ module ::JdbcSpec
|
|
82
84
|
"''"
|
83
85
|
elsif column && column.type == :binary
|
84
86
|
"'#{value.unpack("H*")}'"
|
87
|
+
elsif column.respond_to?(:primary) && column.primary
|
88
|
+
value.to_i.to_s
|
85
89
|
else
|
86
90
|
"'#{quote_string(value)}'"
|
87
91
|
end
|
88
|
-
else
|
92
|
+
else
|
93
|
+
super
|
89
94
|
end
|
90
95
|
end
|
91
96
|
|
@@ -73,13 +73,20 @@ module JdbcSpec
|
|
73
73
|
return "X'#{quote_string(value.unpack("C*").collect {|v| v.to_s(16)}.join)}'"
|
74
74
|
end
|
75
75
|
case value
|
76
|
-
when String
|
77
|
-
|
78
|
-
when
|
79
|
-
|
80
|
-
when
|
81
|
-
|
82
|
-
|
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)}'}
|
83
90
|
end
|
84
91
|
end
|
85
92
|
|
@@ -31,6 +31,10 @@ module ::JdbcSpec
|
|
31
31
|
[/sqlserver|tds/i, lambda {|cfg,col| col.extend(::JdbcSpec::MsSQL::Column)}]
|
32
32
|
end
|
33
33
|
|
34
|
+
def self.jdbc_connection_class
|
35
|
+
::ActiveRecord::ConnectionAdapters::MssqlJdbcConnection
|
36
|
+
end
|
37
|
+
|
34
38
|
module Column
|
35
39
|
attr_accessor :identity, :is_special
|
36
40
|
|
@@ -69,7 +73,7 @@ module ::JdbcSpec
|
|
69
73
|
|
70
74
|
# JRUBY-2011: Match balanced quotes and parenthesis - 'text',('text') or (text)
|
71
75
|
def unquote_string(value)
|
72
|
-
value.sub(/^\((.*)\)$/,'\1').sub(/^'(.*)'$/,'\1')
|
76
|
+
value.to_s.sub(/^\((.*)\)$/,'\1').sub(/^'(.*)'$/,'\1')
|
73
77
|
end
|
74
78
|
|
75
79
|
def unquote(value)
|
@@ -116,7 +120,7 @@ module ::JdbcSpec
|
|
116
120
|
value = column.type == :integer ? value.to_i : value.to_f
|
117
121
|
value.to_s
|
118
122
|
else
|
119
|
-
"'#{quote_string(value)}'" # ' (for ruby-mode)
|
123
|
+
"N'#{quote_string(value)}'" # ' (for ruby-mode)
|
120
124
|
end
|
121
125
|
when TrueClass then '1'
|
122
126
|
when FalseClass then '0'
|
@@ -138,6 +142,14 @@ module ::JdbcSpec
|
|
138
142
|
"[#{name}]"
|
139
143
|
end
|
140
144
|
|
145
|
+
def quoted_true
|
146
|
+
quote true
|
147
|
+
end
|
148
|
+
|
149
|
+
def quoted_false
|
150
|
+
quote false
|
151
|
+
end
|
152
|
+
|
141
153
|
def change_order_direction(order)
|
142
154
|
order.split(",").collect {|fragment|
|
143
155
|
case fragment
|
@@ -249,6 +261,10 @@ module ::JdbcSpec
|
|
249
261
|
end
|
250
262
|
end
|
251
263
|
|
264
|
+
#SELECT .. FOR UPDATE is not supported on Microsoft SQL Server
|
265
|
+
def add_lock!(sql, options)
|
266
|
+
sql
|
267
|
+
end
|
252
268
|
|
253
269
|
private
|
254
270
|
# Turns IDENTITY_INSERT ON for table during execution of the block
|
@@ -5,7 +5,10 @@ module ::JdbcSpec
|
|
5
5
|
$LOADED_FEATURES << "active_record/connection_adapters/mysql_adapter.rb"
|
6
6
|
|
7
7
|
module ActiveRecordExtensions
|
8
|
+
add_method_to_remove_from_ar_base(:mysql_connection)
|
9
|
+
|
8
10
|
def mysql_connection(config)
|
11
|
+
require File.dirname(__FILE__) + "/../active_record/connection_adapters/mysql_adapter"
|
9
12
|
config[:port] ||= 3306
|
10
13
|
url_options = "zeroDateTimeBehavior=convertToNull&jdbcCompliantTruncation=false&useUnicode=true&characterEncoding="
|
11
14
|
url_options << (config[:encoding] || 'utf8')
|
@@ -26,6 +26,9 @@ module ::JdbcSpec
|
|
26
26
|
ActiveRecord::Base.after_save :after_save_with_oracle_lob
|
27
27
|
@lob_callback_added = true
|
28
28
|
end
|
29
|
+
mod.class_eval do
|
30
|
+
alias_chained_method :insert, :query_dirty, :jdbc_oracle_insert
|
31
|
+
end
|
29
32
|
end
|
30
33
|
|
31
34
|
def self.adapter_matcher(name, *)
|
@@ -67,14 +70,14 @@ module ::JdbcSpec
|
|
67
70
|
private
|
68
71
|
def simplified_type(field_type)
|
69
72
|
case field_type
|
70
|
-
when /^number\(1\)$/i
|
71
|
-
when /char/i
|
72
|
-
when /float|double/i
|
73
|
-
when /int/i
|
74
|
-
when /num|dec|real/i
|
75
|
-
when /date|time/i
|
76
|
-
when /clob/i
|
77
|
-
when /blob/i
|
73
|
+
when /^number\(1\)$/i then :boolean
|
74
|
+
when /char/i then :string
|
75
|
+
when /float|double/i then :float
|
76
|
+
when /int/i then :integer
|
77
|
+
when /num|dec|real/i then @scale == 0 ? :integer : :decimal
|
78
|
+
when /date|time/i then :datetime
|
79
|
+
when /clob/i then :text
|
80
|
+
when /blob/i then :binary
|
78
81
|
end
|
79
82
|
end
|
80
83
|
|
@@ -87,6 +90,9 @@ module ::JdbcSpec
|
|
87
90
|
|
88
91
|
return nil if value == "null"
|
89
92
|
|
93
|
+
# sysdate default should be treated like a null value
|
94
|
+
return nil if value.downcase == "sysdate"
|
95
|
+
|
90
96
|
# jdbc returns column default strings with actual single quotes around the value.
|
91
97
|
return $1 if value =~ /^'(.*)'$/
|
92
98
|
|
@@ -132,8 +138,8 @@ module ::JdbcSpec
|
|
132
138
|
recreate_database(name)
|
133
139
|
end
|
134
140
|
|
135
|
-
def
|
136
|
-
if id_value # Pre-assigned id
|
141
|
+
def jdbc_oracle_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
|
142
|
+
if id_value || pk.nil? # Pre-assigned id or table without a primary key
|
137
143
|
execute sql, name
|
138
144
|
else # Assume the sql contains a bind-variable for the id
|
139
145
|
# Extract the table from the insert sql. Yuck.
|
@@ -153,7 +159,7 @@ module ::JdbcSpec
|
|
153
159
|
|
154
160
|
def _execute(sql, name = nil)
|
155
161
|
case sql.strip
|
156
|
-
when /\A\(?\s*(select|show)/i
|
162
|
+
when /\A\(?\s*(select|show)/i then
|
157
163
|
@connection.execute_query(sql)
|
158
164
|
else
|
159
165
|
@connection.execute_update(sql)
|
@@ -308,13 +314,13 @@ module ::JdbcSpec
|
|
308
314
|
# see: abstract/quoting.rb
|
309
315
|
|
310
316
|
# Camelcase column names need to be quoted.
|
311
|
-
# Nonquoted identifiers can contain only alphanumeric characters from your
|
317
|
+
# Nonquoted identifiers can contain only alphanumeric characters from your
|
312
318
|
# database character set and the underscore (_), dollar sign ($), and pound sign (#).
|
313
319
|
# Database links can also contain periods (.) and "at" signs (@).
|
314
320
|
# Oracle strongly discourages you from using $ and # in nonquoted identifiers.
|
315
321
|
# Source: http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/sql_elements008.htm
|
316
322
|
def quote_column_name(name) #:nodoc:
|
317
|
-
name.to_s =~ /^[a-
|
323
|
+
name.to_s =~ /^[a-z0-9_$#]+$/ ? name.to_s : "\"#{name}\""
|
318
324
|
end
|
319
325
|
|
320
326
|
def quote_string(string) #:nodoc:
|
@@ -329,6 +335,9 @@ module ::JdbcSpec
|
|
329
335
|
%Q{empty_#{ column.sql_type.downcase rescue 'blob' }()}
|
330
336
|
end
|
331
337
|
else
|
338
|
+
if column.respond_to?(:primary) && column.primary
|
339
|
+
return value.to_i.to_s
|
340
|
+
end
|
332
341
|
quoted = super
|
333
342
|
if value.acts_like?(:date) || value.acts_like?(:time)
|
334
343
|
quoted = "#{quoted_date(value)}"
|
@@ -353,7 +362,7 @@ module ::JdbcSpec
|
|
353
362
|
# In Oracle, schemas are created under your username:
|
354
363
|
# http://www.oracle.com/technology/obe/2day_dba/schema/schema.htm
|
355
364
|
def oracle_schema
|
356
|
-
@config[:username].to_s
|
365
|
+
@config[:username].to_s if @config[:username]
|
357
366
|
end
|
358
367
|
|
359
368
|
def select(sql, name=nil)
|
@@ -365,3 +374,4 @@ module ::JdbcSpec
|
|
365
374
|
end
|
366
375
|
end
|
367
376
|
end
|
377
|
+
|
@@ -4,7 +4,10 @@ module ::JdbcSpec
|
|
4
4
|
$LOADED_FEATURES << "active_record/connection_adapters/postgresql_adapter.rb"
|
5
5
|
|
6
6
|
module ActiveRecordExtensions
|
7
|
+
add_method_to_remove_from_ar_base(:postgresql_connection)
|
8
|
+
|
7
9
|
def postgresql_connection(config)
|
10
|
+
require File.dirname(__FILE__) + "/../active_record/connection_adapters/postgresql_adapter"
|
8
11
|
config[:host] ||= "localhost"
|
9
12
|
config[:port] ||= 5432
|
10
13
|
config[:url] ||= "jdbc:postgresql://#{config[:host]}:#{config[:port]}/#{config[:database]}"
|
@@ -87,10 +90,12 @@ module ::JdbcSpec
|
|
87
90
|
def postgresql_version
|
88
91
|
@postgresql_version ||=
|
89
92
|
begin
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
93
|
+
value = select_value('SELECT version()')
|
94
|
+
if value =~ /PostgreSQL (\d+)\.(\d+)\.(\d+)/
|
95
|
+
($1.to_i * 10000) + ($2.to_i * 100) + $3.to_i
|
96
|
+
else
|
97
|
+
0
|
98
|
+
end
|
94
99
|
end
|
95
100
|
end
|
96
101
|
|
@@ -217,28 +222,36 @@ module ::JdbcSpec
|
|
217
222
|
table = sql.split(" ", 4)[2].gsub('"', '')
|
218
223
|
|
219
224
|
# Try an insert with 'returning id' if available (PG >= 8.2)
|
220
|
-
if supports_insert_with_returning?
|
225
|
+
if supports_insert_with_returning? && id_value.nil? && false # FIXME:
|
226
|
+
# Disabled, as it causes:
|
227
|
+
# ActiveRecord::ActiveRecordError: A result was returned when none was expected
|
228
|
+
# This was previously disabled because postgresql_version returned 0
|
221
229
|
pk, sequence_name = *pk_and_sequence_for(table) unless pk
|
222
230
|
if pk
|
223
|
-
|
224
|
-
clear_query_cache
|
225
|
-
return
|
231
|
+
id_value = select_value("#{sql} RETURNING #{quote_column_name(pk)}")
|
232
|
+
clear_query_cache #FIXME: Why now?
|
233
|
+
return id_value
|
226
234
|
end
|
227
235
|
end
|
228
236
|
|
229
|
-
# Otherwise, insert
|
237
|
+
# Otherwise, plain insert
|
230
238
|
execute(sql, name)
|
231
239
|
|
232
|
-
#
|
233
|
-
|
234
|
-
|
235
|
-
|
240
|
+
# Don't need to look up id_value if we already have it.
|
241
|
+
# (and can't in case of non-sequence PK)
|
242
|
+
unless id_value
|
243
|
+
# If neither pk nor sequence name is given, look them up.
|
244
|
+
unless pk || sequence_name
|
245
|
+
pk, sequence_name = *pk_and_sequence_for(table)
|
246
|
+
end
|
236
247
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
248
|
+
# If a pk is given, fallback to default sequence name.
|
249
|
+
# Don't fetch last insert id for a table without a pk.
|
250
|
+
if pk && sequence_name ||= default_sequence_name(table, pk)
|
251
|
+
id_value = last_insert_id(table, sequence_name)
|
252
|
+
end
|
241
253
|
end
|
254
|
+
id_value
|
242
255
|
end
|
243
256
|
|
244
257
|
def columns(table_name, name=nil)
|
@@ -332,7 +345,7 @@ module ::JdbcSpec
|
|
332
345
|
|
333
346
|
def _execute(sql, name = nil)
|
334
347
|
case sql.strip
|
335
|
-
when /\A\(?\s*(select|show)/i
|
348
|
+
when /\A\(?\s*(select|show)/i then
|
336
349
|
@connection.execute_query(sql)
|
337
350
|
else
|
338
351
|
@connection.execute_update(sql)
|
@@ -445,6 +458,13 @@ module ::JdbcSpec
|
|
445
458
|
execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DEFAULT '#{default}'"
|
446
459
|
end
|
447
460
|
|
461
|
+
def change_column_null(table_name, column_name, null, default = nil)
|
462
|
+
unless null || default.nil?
|
463
|
+
execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
464
|
+
end
|
465
|
+
execute("ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL")
|
466
|
+
end
|
467
|
+
|
448
468
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
449
469
|
execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
|
450
470
|
end
|
@@ -1,6 +1,13 @@
|
|
1
1
|
module ::JdbcSpec
|
2
|
+
# Don't need to load native postgres adapter
|
3
|
+
$LOADED_FEATURES << "active_record/connection_adapters/sqlite3_adapter.rb"
|
4
|
+
|
2
5
|
module ActiveRecordExtensions
|
6
|
+
add_method_to_remove_from_ar_base(:sqlite3_connection)
|
7
|
+
|
3
8
|
def sqlite3_connection(config)
|
9
|
+
require File.dirname(__FILE__) + "/../active_record/connection_adapters/sqlite3_adapter"
|
10
|
+
|
4
11
|
parse_sqlite3_config!(config)
|
5
12
|
|
6
13
|
config[:url] ||= "jdbc:sqlite:#{config[:database]}"
|
@@ -34,12 +41,15 @@ module ::JdbcSpec
|
|
34
41
|
end
|
35
42
|
|
36
43
|
module Column
|
44
|
+
def init_column(name, default, *args)
|
45
|
+
@default = '' if default =~ /NULL/
|
46
|
+
end
|
37
47
|
|
38
48
|
def type_cast(value)
|
39
49
|
return nil if value.nil?
|
40
50
|
case type
|
41
51
|
when :string then value
|
42
|
-
when :integer then
|
52
|
+
when :integer then JdbcSpec::SQLite3::Column.cast_to_integer(value)
|
43
53
|
when :primary_key then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
44
54
|
when :float then value.to_f
|
45
55
|
when :datetime then JdbcSpec::SQLite3::Column.cast_to_date_or_time(value)
|
@@ -51,11 +61,23 @@ module ::JdbcSpec
|
|
51
61
|
end
|
52
62
|
end
|
53
63
|
|
64
|
+
def type_cast_code(var_name)
|
65
|
+
case type
|
66
|
+
when :integer then "JdbcSpec::SQLite3::Column.cast_to_integer(#{var_name})"
|
67
|
+
when :datetime then "JdbcSpec::SQLite3::Column.cast_to_date_or_time(#{var_name})"
|
68
|
+
when :date then "JdbcSpec::SQLite3::Column.cast_to_date_or_time(#{var_name})"
|
69
|
+
when :time then "JdbcSpec::SQLite3::Column.cast_to_time(#{var_name})"
|
70
|
+
else
|
71
|
+
super
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
54
75
|
private
|
55
76
|
def simplified_type(field_type)
|
56
77
|
case field_type
|
57
78
|
when /boolean/i then :boolean
|
58
|
-
when /text/i then :
|
79
|
+
when /text/i then :text
|
80
|
+
when /varchar/i then :string
|
59
81
|
when /int/i then :integer
|
60
82
|
when /float/i then :float
|
61
83
|
when /real/i then @scale == 0 ? :integer : :decimal
|
@@ -89,6 +111,11 @@ module ::JdbcSpec
|
|
89
111
|
value
|
90
112
|
end
|
91
113
|
|
114
|
+
def self.cast_to_integer(value)
|
115
|
+
return nil if value =~ /NULL/ or value.to_s.empty? or value.nil?
|
116
|
+
return (value.to_i) ? value.to_i : (value ? 1 : 0)
|
117
|
+
end
|
118
|
+
|
92
119
|
def self.cast_to_date_or_time(value)
|
93
120
|
return value if value.is_a? Date
|
94
121
|
return nil if value.blank?
|
@@ -125,7 +152,8 @@ module ::JdbcSpec
|
|
125
152
|
end
|
126
153
|
|
127
154
|
def modify_types(tp)
|
128
|
-
tp[:primary_key] = "INTEGER PRIMARY KEY AUTOINCREMENT"
|
155
|
+
tp[:primary_key] = "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"
|
156
|
+
tp[:string] = { :name => "VARCHAR", :limit => 255 }
|
129
157
|
tp[:float] = { :name => "REAL" }
|
130
158
|
tp[:decimal] = { :name => "REAL" }
|
131
159
|
tp[:datetime] = { :name => "DATETIME" }
|
@@ -142,6 +170,10 @@ module ::JdbcSpec
|
|
142
170
|
when String
|
143
171
|
if column && column.type == :binary
|
144
172
|
"'#{quote_string(column.class.string_to_binary(value))}'"
|
173
|
+
elsif column && [:integer, :float].include?(column.type)
|
174
|
+
(column.type == :integer ? value.to_i : value.to_f).to_s
|
175
|
+
elsif column && column.respond_to?(:primary) && column.primary
|
176
|
+
value.to_i.to_s
|
145
177
|
else
|
146
178
|
"'#{quote_string(value)}'"
|
147
179
|
end
|
@@ -184,34 +216,38 @@ module ::JdbcSpec
|
|
184
216
|
end
|
185
217
|
end
|
186
218
|
|
187
|
-
def remove_column(table_name,
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
@connection.begin
|
194
|
-
|
195
|
-
execute "CREATE TEMPORARY TABLE #{table_backup}(#{cols})"
|
196
|
-
insert "INSERT INTO #{table_backup} SELECT #{cols} FROM #{table_name}"
|
197
|
-
execute "DROP TABLE #{table_name}"
|
198
|
-
execute "CREATE TABLE #{table_name}(#{cols})"
|
199
|
-
insert "INSERT INTO #{table_name} SELECT #{cols} FROM #{table_backup}"
|
200
|
-
execute "DROP TABLE #{table_backup}"
|
201
|
-
|
202
|
-
@connection.commit
|
219
|
+
def remove_column(table_name, *column_names) #:nodoc:
|
220
|
+
column_names.flatten.each do |column_name|
|
221
|
+
alter_table(table_name) do |definition|
|
222
|
+
definition.columns.delete(definition[column_name])
|
223
|
+
end
|
224
|
+
end
|
203
225
|
end
|
226
|
+
alias :remove_columns :remove_column
|
204
227
|
|
205
228
|
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
206
|
-
|
229
|
+
alter_table(table_name) do |definition|
|
230
|
+
include_default = options_include_default?(options)
|
231
|
+
definition[column_name].instance_eval do
|
232
|
+
self.type = type
|
233
|
+
self.limit = options[:limit] if options.include?(:limit)
|
234
|
+
self.default = options[:default] if include_default
|
235
|
+
self.null = options[:null] if options.include?(:null)
|
236
|
+
end
|
237
|
+
end
|
207
238
|
end
|
208
239
|
|
209
240
|
def change_column_default(table_name, column_name, default) #:nodoc:
|
210
|
-
|
241
|
+
alter_table(table_name) do |definition|
|
242
|
+
definition[column_name].default = default
|
243
|
+
end
|
211
244
|
end
|
212
245
|
|
213
246
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
214
|
-
|
247
|
+
unless columns(table_name).detect{|c| c.name == column_name.to_s }
|
248
|
+
raise ActiveRecord::ActiveRecordError, "Missing column #{table_name}.#{column_name}"
|
249
|
+
end
|
250
|
+
alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
|
215
251
|
end
|
216
252
|
|
217
253
|
def rename_table(name, new_name)
|
@@ -221,6 +257,7 @@ module ::JdbcSpec
|
|
221
257
|
def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
|
222
258
|
log(sql,name) do
|
223
259
|
@connection.execute_update(sql)
|
260
|
+
clear_query_cache
|
224
261
|
end
|
225
262
|
table = sql.split(" ", 4)[2]
|
226
263
|
id_value || last_insert_id(table, nil)
|
@@ -237,8 +274,16 @@ module ::JdbcSpec
|
|
237
274
|
end
|
238
275
|
end
|
239
276
|
|
240
|
-
def tables
|
241
|
-
|
277
|
+
def tables(name = nil) #:nodoc:
|
278
|
+
sql = <<-SQL
|
279
|
+
SELECT name
|
280
|
+
FROM sqlite_master
|
281
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
282
|
+
SQL
|
283
|
+
|
284
|
+
select_rows(sql, name).map do |row|
|
285
|
+
row[0]
|
286
|
+
end
|
242
287
|
end
|
243
288
|
|
244
289
|
def remove_index(table_name, options = {})
|
@@ -256,6 +301,11 @@ module ::JdbcSpec
|
|
256
301
|
::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, name, unique, cols)
|
257
302
|
end
|
258
303
|
end
|
304
|
+
|
305
|
+
def primary_key(table_name) #:nodoc:
|
306
|
+
column = table_structure(table_name).find {|field| field['pk'].to_i == 1}
|
307
|
+
column ? column['name'] : nil
|
308
|
+
end
|
259
309
|
|
260
310
|
def recreate_database(name)
|
261
311
|
tables.each{ |table| drop_table(table) }
|
@@ -269,7 +319,19 @@ module ::JdbcSpec
|
|
269
319
|
ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql) ? last_insert_id(sql.split(" ", 4)[2], nil) : affected_rows
|
270
320
|
end
|
271
321
|
end
|
272
|
-
|
322
|
+
|
323
|
+
def select(sql, name=nil)
|
324
|
+
execute(sql, name).map do |row|
|
325
|
+
record = {}
|
326
|
+
row.each_key do |key|
|
327
|
+
if key.is_a?(String)
|
328
|
+
record[key.sub(/^"?\w+"?\./, '')] = row[key]
|
329
|
+
end
|
330
|
+
end
|
331
|
+
record
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
273
335
|
def table_structure(table_name)
|
274
336
|
returning structure = @connection.execute_query("PRAGMA table_info(#{quote_table_name(table_name)})") do
|
275
337
|
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
|
@@ -278,9 +340,17 @@ module ::JdbcSpec
|
|
278
340
|
|
279
341
|
def columns(table_name, name = nil) #:nodoc:
|
280
342
|
table_structure(table_name).map do |field|
|
281
|
-
::ActiveRecord::ConnectionAdapters::JdbcColumn.new(@config, field['name'], field['dflt_value'], field['type'], field['notnull'] ==
|
343
|
+
::ActiveRecord::ConnectionAdapters::JdbcColumn.new(@config, field['name'], field['dflt_value'], field['type'], field['notnull'] == 0)
|
282
344
|
end
|
283
345
|
end
|
346
|
+
|
347
|
+
# SELECT ... FOR UPDATE is redundant since the table is locked.
|
348
|
+
def add_lock!(sql, options) #:nodoc:
|
349
|
+
sql
|
350
|
+
end
|
351
|
+
|
352
|
+
protected
|
353
|
+
include JdbcSpec::MissingFunctionalityHelper
|
284
354
|
end
|
285
355
|
end
|
286
356
|
|