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.
Files changed (65) hide show
  1. data/History.txt +61 -0
  2. data/LICENSE +21 -0
  3. data/Manifest.txt +64 -0
  4. data/README.txt +116 -0
  5. data/Rakefile +146 -0
  6. data/lib/active_record/connection_adapters/derby_adapter.rb +13 -0
  7. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  8. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +13 -0
  9. data/lib/active_record/connection_adapters/jdbc_adapter.rb +575 -0
  10. data/lib/active_record/connection_adapters/jdbc_adapter_spec.rb +10 -0
  11. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  12. data/lib/active_record/connection_adapters/mysql_adapter.rb +13 -0
  13. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  14. data/lib/active_record/connection_adapters/postgresql_adapter.rb +13 -0
  15. data/lib/jdbc_adapter.rb +32 -0
  16. data/lib/jdbc_adapter/jdbc_db2.rb +104 -0
  17. data/lib/jdbc_adapter/jdbc_derby.rb +362 -0
  18. data/lib/jdbc_adapter/jdbc_firebird.rb +109 -0
  19. data/lib/jdbc_adapter/jdbc_hsqldb.rb +168 -0
  20. data/lib/jdbc_adapter/jdbc_mimer.rb +134 -0
  21. data/lib/jdbc_adapter/jdbc_mssql.rb +356 -0
  22. data/lib/jdbc_adapter/jdbc_mysql.rb +168 -0
  23. data/lib/jdbc_adapter/jdbc_oracle.rb +340 -0
  24. data/lib/jdbc_adapter/jdbc_postgre.rb +347 -0
  25. data/lib/jdbc_adapter/missing_functionality_helper.rb +72 -0
  26. data/lib/jdbc_adapter/version.rb +5 -0
  27. data/lib/jdbc_adapter_internal.jar +0 -0
  28. data/lib/tasks/jdbc_databases.rake +72 -0
  29. data/src/java/JDBCDerbySpec.java +323 -0
  30. data/src/java/JDBCMySQLSpec.java +89 -0
  31. data/src/java/JdbcAdapterInternalService.java +953 -0
  32. data/test/activerecord/connection_adapters/type_conversion_test.rb +31 -0
  33. data/test/activerecord/connections/native_jdbc_mysql/connection.rb +25 -0
  34. data/test/db/derby.rb +18 -0
  35. data/test/db/h2.rb +11 -0
  36. data/test/db/hsqldb.rb +15 -0
  37. data/test/db/jdbc.rb +11 -0
  38. data/test/db/jndi_config.rb +30 -0
  39. data/test/db/logger.rb +3 -0
  40. data/test/db/mysql.rb +9 -0
  41. data/test/db/postgres.rb +9 -0
  42. data/test/derby_multibyte_test.rb +12 -0
  43. data/test/derby_simple_test.rb +12 -0
  44. data/test/generic_jdbc_connection_test.rb +9 -0
  45. data/test/h2_simple_test.rb +7 -0
  46. data/test/hsqldb_simple_test.rb +6 -0
  47. data/test/jdbc_adapter/jdbc_db2_test.rb +21 -0
  48. data/test/jdbc_common.rb +6 -0
  49. data/test/jndi_test.rb +37 -0
  50. data/test/manualTestDatabase.rb +195 -0
  51. data/test/minirunit.rb +109 -0
  52. data/test/minirunit/testConnect.rb +14 -0
  53. data/test/minirunit/testH2.rb +73 -0
  54. data/test/minirunit/testHsqldb.rb +73 -0
  55. data/test/minirunit/testLoadActiveRecord.rb +3 -0
  56. data/test/minirunit/testMysql.rb +83 -0
  57. data/test/minirunit/testRawSelect.rb +24 -0
  58. data/test/models/auto_id.rb +18 -0
  59. data/test/models/data_types.rb +18 -0
  60. data/test/models/entry.rb +20 -0
  61. data/test/mysql_multibyte_test.rb +6 -0
  62. data/test/mysql_simple_test.rb +13 -0
  63. data/test/postgres_simple_test.rb +12 -0
  64. data/test/simple.rb +157 -0
  65. metadata +112 -0
@@ -0,0 +1,168 @@
1
+ require 'active_record/connection_adapters/abstract/schema_definitions'
2
+
3
+ module ::JdbcSpec
4
+ module ActiveRecordExtensions
5
+ def mysql_connection(config)
6
+ if config[:socket]
7
+ warn "AR-JDBC MySQL on JRuby does not support sockets"
8
+ end
9
+ config[:port] ||= 3306
10
+ config[:url] ||= "jdbc:mysql://#{config[:host]}:#{config[:port]}/#{config[:database]}?zeroDateTimeBehavior=convertToNull&jdbcCompliantTruncation=false&useUnicode=true&characterEncoding=utf8"
11
+ config[:driver] = "com.mysql.jdbc.Driver"
12
+ jdbc_connection(config)
13
+ end
14
+ end
15
+
16
+ module MySQL
17
+ def self.column_selector
18
+ [/mysql/i, lambda {|cfg,col| col.extend(::JdbcSpec::MySQL::Column)}]
19
+ end
20
+
21
+ def self.adapter_selector
22
+ [/mysql/i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::MySQL)}]
23
+ end
24
+
25
+ def self.extended(adapter)
26
+ adapter.execute("SET SQL_AUTO_IS_NULL=0")
27
+ end
28
+
29
+ module Column
30
+ TYPES_ALLOWING_EMPTY_STRING_DEFAULT = Set.new([:binary, :string, :text])
31
+
32
+ def simplified_type(field_type)
33
+ return :boolean if field_type =~ /tinyint\(1\)|bit/i
34
+ return :string if field_type =~ /enum/i
35
+ super
36
+ end
37
+
38
+ def init_column(name, default, *args)
39
+ @original_default = default
40
+ @default = nil if missing_default_forged_as_empty_string?
41
+ end
42
+
43
+ # MySQL misreports NOT NULL column default when none is given.
44
+ # We can't detect this for columns which may have a legitimate ''
45
+ # default (string, text, binary) but we can for others (integer,
46
+ # datetime, boolean, and the rest).
47
+ #
48
+ # Test whether the column has default '', is not null, and is not
49
+ # a type allowing default ''.
50
+ def missing_default_forged_as_empty_string?
51
+ !null && @original_default == '' && !TYPES_ALLOWING_EMPTY_STRING_DEFAULT.include?(type)
52
+ end
53
+ end
54
+
55
+ def modify_types(tp)
56
+ tp[:primary_key] = "int(11) DEFAULT NULL auto_increment PRIMARY KEY"
57
+ tp[:decimal] = { :name => "decimal" }
58
+ tp[:timestamp] = { :name => "datetime" }
59
+ tp[:datetime][:limit] = nil
60
+ tp
61
+ end
62
+
63
+ # QUOTING ==================================================
64
+
65
+ def quote(value, column = nil)
66
+ return value.quoted_id if value.respond_to?(:quoted_id)
67
+
68
+ if column && column.type == :primary_key
69
+ value.to_s
70
+ elsif column && String === value && column.type == :binary && column.class.respond_to?(:string_to_binary)
71
+ s = column.class.string_to_binary(value).unpack("H*")[0]
72
+ "x'#{s}'"
73
+ elsif BigDecimal === value
74
+ "'#{value.to_s("F")}'"
75
+ else
76
+ super
77
+ end
78
+ end
79
+
80
+ def quote_column_name(name) #:nodoc:
81
+ "`#{name}`"
82
+ end
83
+
84
+ def quoted_true
85
+ "1"
86
+ end
87
+
88
+ def quoted_false
89
+ "0"
90
+ end
91
+
92
+ # SCHEMA STATEMENTS ========================================
93
+
94
+ def structure_dump #:nodoc:
95
+ if supports_views?
96
+ sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"
97
+ else
98
+ sql = "SHOW TABLES"
99
+ end
100
+
101
+ select_all(sql).inject("") do |structure, table|
102
+ table.delete('Table_type')
103
+ structure += select_one("SHOW CREATE TABLE #{table.to_a.first.last}")["Create Table"] + ";\n\n"
104
+ end
105
+ end
106
+
107
+ def recreate_database(name) #:nodoc:
108
+ drop_database(name)
109
+ create_database(name)
110
+ end
111
+
112
+ def create_database(name) #:nodoc:
113
+ execute "CREATE DATABASE `#{name}`"
114
+ end
115
+
116
+ def drop_database(name) #:nodoc:
117
+ execute "DROP DATABASE IF EXISTS `#{name}`"
118
+ end
119
+
120
+ def current_database
121
+ select_one("SELECT DATABASE() as db")["db"]
122
+ end
123
+
124
+ def create_table(name, options = {}) #:nodoc:
125
+ super(name, {:options => "ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin"}.merge(options))
126
+ end
127
+
128
+ def rename_table(name, new_name)
129
+ execute "RENAME TABLE #{name} TO #{new_name}"
130
+ end
131
+
132
+ def change_column_default(table_name, column_name, default) #:nodoc:
133
+ current_type = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Type"]
134
+
135
+ execute("ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{current_type} DEFAULT #{quote(default)}")
136
+ end
137
+
138
+ def change_column(table_name, column_name, type, options = {}) #:nodoc:
139
+ unless options.include?(:default) && !(options[:null] == false && options[:default].nil?)
140
+ options[:default] = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Default"]
141
+ end
142
+
143
+ change_column_sql = "ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
144
+ add_column_options!(change_column_sql, options)
145
+ execute(change_column_sql)
146
+ end
147
+
148
+ def rename_column(table_name, column_name, new_column_name) #:nodoc:
149
+ current_type = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Type"]
150
+ execute "ALTER TABLE #{table_name} CHANGE #{column_name} #{new_column_name} #{current_type}"
151
+ end
152
+
153
+ def add_limit_offset!(sql, options) #:nodoc:
154
+ if limit = options[:limit]
155
+ unless offset = options[:offset]
156
+ sql << " LIMIT #{limit}"
157
+ else
158
+ sql << " LIMIT #{offset}, #{limit}"
159
+ end
160
+ end
161
+ end
162
+
163
+ private
164
+ def supports_views?
165
+ false
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,340 @@
1
+ module ::ActiveRecord
2
+ class Base
3
+ # After setting large objects to empty, write data back with a helper method
4
+ alias after_save_without_oracle_lob after_save
5
+
6
+ def after_save_with_oracle_lob() #:nodoc:
7
+ if connection.is_a?(JdbcSpec::Oracle)
8
+ self.class.columns.select { |c| c.sql_type =~ /LOB\(|LOB$/i }.each { |c|
9
+ value = self[c.name]
10
+ value = value.to_yaml if unserializable_attribute?(c.name, c)
11
+ next if value.nil? || (value == '')
12
+
13
+ connection.write_large_object(c.type == :binary, c.name, self.class.table_name, self.class.primary_key, quote_value(id), value)
14
+ }
15
+ end
16
+ after_save_without_oracle_lob
17
+ end
18
+
19
+ alias after_save after_save_with_oracle_lob
20
+ end
21
+ end
22
+
23
+ module ::JdbcSpec
24
+ module ActiveRecordExtensions
25
+ def oracle_connection(config)
26
+ config[:port] ||= 1521
27
+ config[:url] ||= "jdbc:oracle:thin:@#{config[:host]}:#{config[:port]}:#{config[:database]}"
28
+ config[:driver] ||= "oracle.jdbc.driver.OracleDriver"
29
+ jdbc_connection(config)
30
+ end
31
+ end
32
+
33
+ module Oracle
34
+ def self.column_selector
35
+ [/oracle/i, lambda {|cfg,col| col.extend(::JdbcSpec::Oracle::Column)}]
36
+ end
37
+
38
+ def self.adapter_selector
39
+ [/oracle/i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::Oracle)
40
+ =begin
41
+ (adapt.methods - %w(send __send__ id class methods is_a? kind_of? verify! active?)).each do |name|
42
+ new_name = "__#{name}"
43
+ (class << adapt; self; end).send :alias_method, new_name, name
44
+ (class << adapt; self; end).send :define_method, name do |*args|
45
+ puts "#{name}(#{args.inspect})"
46
+ adapt.send new_name, *args
47
+ end
48
+ end
49
+ =end
50
+ }]
51
+ end
52
+
53
+ module Column
54
+ def type_cast(value)
55
+ return nil if value.nil?
56
+ case type
57
+ when :string then value
58
+ when :integer then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
59
+ when :primary_key then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
60
+ when :float then value.to_f
61
+ when :datetime then JdbcSpec::Oracle::Column.cast_to_date_or_time(value)
62
+ when :time then JdbcSpec::Oracle::Column.cast_to_time(value)
63
+ when :decimal then self.class.value_to_decimal(value)
64
+ when :boolean then self.class.value_to_boolean(value)
65
+ else value
66
+ end
67
+ end
68
+
69
+ def type_cast_code(var_name)
70
+ return "JdbcSpec::Oracle::Column.cast_to_date_or_time(#{var_name})" if type == :datetime
71
+ super
72
+ end
73
+
74
+ private
75
+ def simplified_type(field_type)
76
+ case field_type
77
+ when /^number\(1\)$/i : :boolean
78
+ when /char/i : :string
79
+ when /float|double/i : :float
80
+ when /int/i : :integer
81
+ when /num|dec|real/i : @scale == 0 ? :integer : :decimal
82
+ when /date|time/i : :datetime
83
+ when /clob/i : :text
84
+ when /blob/i : :binary
85
+ end
86
+ end
87
+
88
+ def self.cast_to_date_or_time(value)
89
+ return value if value.is_a? Date
90
+ return nil if value.blank?
91
+ guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
92
+ end
93
+
94
+ def self.cast_to_time(value)
95
+ return value if value.is_a? Time
96
+ time_array = ParseDate.parsedate value
97
+ time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1;
98
+ Time.send(ActiveRecord::Base.default_timezone, *time_array) rescue nil
99
+ end
100
+
101
+ def self.guess_date_or_time(value)
102
+ (value.hour == 0 and value.min == 0 and value.sec == 0) ?
103
+ Date.new(value.year, value.month, value.day) : value
104
+ end
105
+ end
106
+
107
+ def table_alias_length
108
+ 30
109
+ end
110
+
111
+ def default_sequence_name(table, column) #:nodoc:
112
+ "#{table}_seq"
113
+ end
114
+
115
+ def create_table(name, options = {}) #:nodoc:
116
+ super(name, options)
117
+ seq_name = options[:sequence_name] || "#{name}_seq"
118
+ raise ActiveRecord::StatementInvalid.new("name #{seq_name} too long") if seq_name.length > table_alias_length
119
+ execute "CREATE SEQUENCE #{seq_name} START WITH 10000" unless options[:id] == false
120
+ end
121
+
122
+ def rename_table(name, new_name) #:nodoc:
123
+ execute "RENAME #{name} TO #{new_name}"
124
+ execute "RENAME #{name}_seq TO #{new_name}_seq" rescue nil
125
+ end
126
+
127
+ def drop_table(name, options = {}) #:nodoc:
128
+ super(name)
129
+ seq_name = options[:sequence_name] || "#{name}_seq"
130
+ execute "DROP SEQUENCE #{seq_name}" rescue nil
131
+ end
132
+
133
+ def recreate_database(name)
134
+ tables.each{ |table| drop_table(table) }
135
+ end
136
+
137
+ def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
138
+ if pk.nil? # Who called us? What does the sql look like? No idea!
139
+ execute sql, name
140
+ elsif id_value # Pre-assigned id
141
+ execute sql, name
142
+ else # Assume the sql contains a bind-variable for the id
143
+ id_value = select_one("select #{sequence_name}.nextval id from dual")['id'].to_i
144
+ log(sql, name) {
145
+ @connection.execute_id_insert(sql,id_value)
146
+ }
147
+ end
148
+ id_value
149
+ end
150
+
151
+ def indexes(table, name = nil)
152
+ @connection.indexes(table, name, @connection.connection.meta_data.user_name)
153
+ end
154
+
155
+ def _execute(sql, name = nil)
156
+ case sql.strip
157
+ when /\A\(?\s*(select|show)/i:
158
+ @connection.execute_query(sql)
159
+ else
160
+ @connection.execute_update(sql)
161
+ end
162
+ end
163
+
164
+ def modify_types(tp)
165
+ tp[:primary_key] = "NUMBER(38) NOT NULL PRIMARY KEY"
166
+ tp[:integer] = { :name => "NUMBER", :limit => 38 }
167
+ tp[:datetime] = { :name => "DATE" }
168
+ tp[:timestamp] = { :name => "DATE" }
169
+ tp[:time] = { :name => "DATE" }
170
+ tp[:date] = { :name => "DATE" }
171
+ tp
172
+ end
173
+
174
+ def add_limit_offset!(sql, options) #:nodoc:
175
+ offset = options[:offset] || 0
176
+
177
+ if limit = options[:limit]
178
+ sql.replace "select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_ where rownum <= #{offset+limit}) where raw_rnum_ > #{offset}"
179
+ elsif offset > 0
180
+ sql.replace "select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_) where raw_rnum_ > #{offset}"
181
+ end
182
+ end
183
+
184
+ def current_database #:nodoc:
185
+ select_one("select sys_context('userenv','db_name') db from dual")["db"]
186
+ end
187
+
188
+ def remove_index(table_name, options = {}) #:nodoc:
189
+ execute "DROP INDEX #{index_name(table_name, options)}"
190
+ end
191
+
192
+ def change_column_default(table_name, column_name, default) #:nodoc:
193
+ execute "ALTER TABLE #{table_name} MODIFY #{column_name} DEFAULT #{quote(default)}"
194
+ end
195
+
196
+ def change_column(table_name, column_name, type, options = {}) #:nodoc:
197
+ change_column_sql = "ALTER TABLE #{table_name} MODIFY #{column_name} #{type_to_sql(type, options[:limit])}"
198
+ add_column_options!(change_column_sql, options)
199
+ execute(change_column_sql)
200
+ end
201
+
202
+ def rename_column(table_name, column_name, new_column_name) #:nodoc:
203
+ execute "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} to #{new_column_name}"
204
+ end
205
+
206
+ def remove_column(table_name, column_name) #:nodoc:
207
+ execute "ALTER TABLE #{table_name} DROP COLUMN #{column_name}"
208
+ end
209
+
210
+ def structure_dump #:nodoc:
211
+ s = select_all("select sequence_name from user_sequences").inject("") do |structure, seq|
212
+ structure << "create sequence #{seq.to_a.first.last};\n\n"
213
+ end
214
+
215
+ select_all("select table_name from user_tables").inject(s) do |structure, table|
216
+ ddl = "create table #{table.to_a.first.last} (\n "
217
+ cols = select_all(%Q{
218
+ select column_name, data_type, data_length, data_precision, data_scale, data_default, nullable
219
+ from user_tab_columns
220
+ where table_name = '#{table.to_a.first.last}'
221
+ order by column_id
222
+ }).map do |row|
223
+ row = row.inject({}) do |h,args|
224
+ h[args[0].downcase] = args[1]
225
+ h
226
+ end
227
+ col = "#{row['column_name'].downcase} #{row['data_type'].downcase}"
228
+ if row['data_type'] =='NUMBER' and !row['data_precision'].nil?
229
+ col << "(#{row['data_precision'].to_i}"
230
+ col << ",#{row['data_scale'].to_i}" if !row['data_scale'].nil?
231
+ col << ')'
232
+ elsif row['data_type'].include?('CHAR')
233
+ col << "(#{row['data_length'].to_i})"
234
+ end
235
+ col << " default #{row['data_default']}" if !row['data_default'].nil?
236
+ col << ' not null' if row['nullable'] == 'N'
237
+ col
238
+ end
239
+ ddl << cols.join(",\n ")
240
+ ddl << ");\n\n"
241
+ structure << ddl
242
+ end
243
+ end
244
+
245
+ def structure_drop #:nodoc:
246
+ s = select_all("select sequence_name from user_sequences").inject("") do |drop, seq|
247
+ drop << "drop sequence #{seq.to_a.first.last};\n\n"
248
+ end
249
+
250
+ select_all("select table_name from user_tables").inject(s) do |drop, table|
251
+ drop << "drop table #{table.to_a.first.last} cascade constraints;\n\n"
252
+ end
253
+ end
254
+
255
+ # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
256
+ #
257
+ # Oracle requires the ORDER BY columns to be in the SELECT list for DISTINCT
258
+ # queries. However, with those columns included in the SELECT DISTINCT list, you
259
+ # won't actually get a distinct list of the column you want (presuming the column
260
+ # has duplicates with multiple values for the ordered-by columns. So we use the
261
+ # FIRST_VALUE function to get a single (first) value for each column, effectively
262
+ # making every row the same.
263
+ #
264
+ # distinct("posts.id", "posts.created_at desc")
265
+ def distinct(columns, order_by)
266
+ return "DISTINCT #{columns}" if order_by.blank?
267
+
268
+ # construct a valid DISTINCT clause, ie. one that includes the ORDER BY columns, using
269
+ # FIRST_VALUE such that the inclusion of these columns doesn't invalidate the DISTINCT
270
+ order_columns = order_by.split(',').map { |s| s.strip }.reject(&:blank?)
271
+ order_columns = order_columns.zip((0...order_columns.size).to_a).map do |c, i|
272
+ "FIRST_VALUE(#{c.split.first}) OVER (PARTITION BY #{columns} ORDER BY #{c}) AS alias_#{i}__"
273
+ end
274
+ sql = "DISTINCT #{columns}, "
275
+ sql << order_columns * ", "
276
+ end
277
+
278
+ # ORDER BY clause for the passed order option.
279
+ #
280
+ # Uses column aliases as defined by #distinct.
281
+ def add_order_by_for_association_limiting!(sql, options)
282
+ return sql if options[:order].blank?
283
+
284
+ order = options[:order].split(',').collect { |s| s.strip }.reject(&:blank?)
285
+ order.map! {|s| $1 if s =~ / (.*)/}
286
+ order = order.zip((0...order.size).to_a).map { |s,i| "alias_#{i}__ #{s}" }.join(', ')
287
+
288
+ sql << "ORDER BY #{order}"
289
+ end
290
+
291
+
292
+ # QUOTING ==================================================
293
+ #
294
+ # see: abstract/quoting.rb
295
+
296
+ # camelCase column names need to be quoted; not that anyone using Oracle
297
+ # would really do this, but handling this case means we pass the test...
298
+ def quote_column_name(name) #:nodoc:
299
+ name.to_s =~ /[A-Z]/ ? "\"#{name}\"" : name.to_s
300
+ end
301
+
302
+ def quote_string(string) #:nodoc:
303
+ string.gsub(/'/, "''")
304
+ end
305
+
306
+ def quote(value, column = nil) #:nodoc:
307
+ return value.quoted_id if value.respond_to?(:quoted_id)
308
+
309
+ if column && [:text, :binary].include?(column.type)
310
+ if /(.*?)\([0-9]+\)/ =~ column.sql_type
311
+ %Q{empty_#{ $1.downcase }()}
312
+ else
313
+ %Q{empty_#{ column.sql_type.downcase rescue 'blob' }()}
314
+ end
315
+ else
316
+ if column && column.type == :primary_key
317
+ return value.to_s
318
+ end
319
+ case value
320
+ when String, ActiveSupport::Multibyte::Chars : %Q{'#{quote_string(value)}'}
321
+ when NilClass : 'null'
322
+ when TrueClass : '1'
323
+ when FalseClass : '0'
324
+ when Numeric : value.to_s
325
+ when Date, Time : %Q{TIMESTAMP'#{value.strftime("%Y-%m-%d %H:%M:%S")}'}
326
+ else %Q{'#{quote_string(value.to_yaml)}'}
327
+ end
328
+ end
329
+ end
330
+
331
+ private
332
+ def select(sql, name=nil)
333
+ records = execute(sql,name)
334
+ records.each do |col|
335
+ col.delete('raw_rnum_')
336
+ end
337
+ records
338
+ end
339
+ end
340
+ end