activerecord-jdbc-adapter 0.6

Sign up to get free protection for your applications and to get access to all the features.
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