ar-extensions 0.7.0 → 0.8.0

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/Rakefile CHANGED
@@ -14,8 +14,12 @@ end
14
14
 
15
15
  ADAPTERS = %w( mysql postgresql sqlite sqlite3 oracle )
16
16
 
17
- namespace :db do
17
+ desc "Packages a rubygem"
18
+ task "pkg" do
19
+
20
+ end
18
21
 
22
+ namespace :db do
19
23
  namespace :test do
20
24
  ADAPTERS.each do |adapter|
21
25
  desc "builds test database for #{adapter}"
@@ -25,21 +29,17 @@ namespace :db do
25
29
  end
26
30
  end
27
31
  end
28
-
29
32
  end
30
33
 
31
34
  namespace :test do
32
-
33
35
  ADAPTERS.each do |adapter|
34
36
  desc "test base extensions for #{adapter}"
35
37
  task adapter do |t|
36
38
  ENV['ARE_DB'] = adapter
37
- Rake::Task[ 'boot' ].invoke
38
-
39
39
  task = Rake::Task[ "db:test:prepare_#{adapter}" ]
40
- begin
40
+ begin
41
41
  task = false if SchemaInfo::VERSION == SchemaInfo.find( :first ).version
42
- rescue Exception => ex
42
+ rescue Exception => ex
43
43
  end
44
44
  task.invoke if task
45
45
 
@@ -48,7 +48,6 @@ namespace :test do
48
48
  end
49
49
 
50
50
  namespace :activerecord do
51
-
52
51
  ADAPTERS.each do |adapter|
53
52
  desc "runs ActiveRecord unit tests for #{adapter} with ActiveRecord::Extensions"
54
53
  task adapter.to_sym do |t|
@@ -67,9 +66,6 @@ namespace :test do
67
66
  Dir.chdir( old_dir )
68
67
  ENV['RUBYOPT'] = old_env
69
68
  end
70
-
71
69
  end
72
-
73
70
  end
74
-
75
- end
71
+ end
@@ -5,6 +5,11 @@ ActiveRecord::Schema.define do
5
5
  end
6
6
  SchemaInfo.create :version=>SchemaInfo::VERSION
7
7
 
8
+ create_table :group, :force => true do |t|
9
+ t.column :order, :string
10
+ t.timestamps
11
+ end
12
+
8
13
  create_table :topics, :force=>true do |t|
9
14
  t.column :title, :string, :null=>false
10
15
  t.column :author_name, :string
@@ -48,11 +53,12 @@ ActiveRecord::Schema.define do
48
53
  t.column :title, :string, :null=>false
49
54
  t.column :publisher, :string, :null=>false
50
55
  t.column :author_name, :string, :null=>false
51
- t.column :created_at, :time
56
+ t.column :created_at, :datetime
52
57
  t.column :created_on, :datetime
53
- t.column :updated_at, :time
58
+ t.column :updated_at, :datetime
54
59
  t.column :updated_on, :datetime
55
60
  t.column :topic_id, :integer
61
+ t.column :for_sale, :boolean, :default => true
56
62
  end
57
63
 
58
64
  create_table :languages, :force=>true do |t|
@@ -24,6 +24,7 @@ ActiveRecord::Schema.define do
24
24
  t.column :updated_at, :datetime
25
25
  t.column :updated_on, :datetime
26
26
  t.column :topic_id, :integer
27
+ t.column :for_sale, :boolean, :default => true
27
28
  end
28
29
  execute "ALTER TABLE books ADD FULLTEXT( `title`, `publisher`, `author_name` )"
29
30
 
@@ -0,0 +1,5 @@
1
+ ActiveRecord::Schema.define do
2
+
3
+ execute "CREATE SEQUENCE books_seq START_WITH 1"
4
+
5
+ end
@@ -1,4 +1,4 @@
1
1
  class SchemaInfo < ActiveRecord::Base
2
2
  set_table_name 'schema_info'
3
- VERSION = 8
3
+ VERSION = 10
4
4
  end
data/init.rb CHANGED
@@ -1,34 +1,13 @@
1
1
  require 'ostruct'
2
2
  begin ; require 'active_record' ; rescue LoadError; require 'rubygems'; require 'active_record'; end
3
3
 
4
- dir = File.dirname( __FILE__ )
5
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'version' ) )
6
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'extensions' ) )
7
-
8
- begin
9
- require 'faster_csv'
10
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'csv' ) )
11
- rescue LoadError
12
- STDERR.puts "FasterCSV is not installed. CSV functionality will not be included."
13
- end
14
-
15
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'foreign_keys' ) )
16
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'fulltext' ) )
17
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'fulltext', 'mysql' ) )
18
-
19
- db_adapters_path = File.expand_path( File.join( dir, 'lib/ar-extensions', 'adapters' ) )
20
-
21
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'import' ) )
22
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'import', 'mysql' ) )
23
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'import', 'postgresql' ) )
24
-
25
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'finders' ) )
26
-
27
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'synchronize' ) )
28
-
29
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'temporary_table' ) )
30
- require File.expand_path( File.join( dir, 'lib/ar-extensions', 'temporary_table', 'mysql' ) )
31
-
32
- require File.expand_path( File.join( db_adapters_path, 'abstract_adapter' ) )
33
- require File.expand_path( File.join( db_adapters_path,'mysql_adapter' ) )
34
-
4
+ $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
5
+ require 'ar-extensions/version'
6
+ require 'ar-extensions/extensions'
7
+ require 'ar-extensions/foreign_keys'
8
+ require 'ar-extensions/fulltext'
9
+ require 'ar-extensions/import'
10
+ require 'ar-extensions/finders'
11
+ require 'ar-extensions/synchronize'
12
+ require 'ar-extensions/temporary_table'
13
+ require 'ar-extensions/adapters/abstract_adapter'
@@ -4,6 +4,10 @@ module ActiveRecord # :nodoc:
4
4
  NO_MAX_PACKET = 0
5
5
  QUERY_OVERHEAD = 8 #This was shown to be true for MySQL, but it's not clear where the overhead is from.
6
6
 
7
+ def next_value_for_sequence(sequence_name)
8
+ %{#{sequence_name}.nextval}
9
+ end
10
+
7
11
  # +sql+ can be a single string or an array. If it is an array all
8
12
  # elements that are in position >= 1 will be appended to the final SQL.
9
13
  def insert_many( sql, values, *args ) # :nodoc:
@@ -52,6 +56,35 @@ module ActiveRecord # :nodoc:
52
56
  instances.each { |e| e.reload }
53
57
  end
54
58
 
59
+ # Returns an array of post SQL statements given the passed in options.
60
+ def post_sql_statements( table_name, options ) # :nodoc:
61
+ post_sql_statements = []
62
+ if options[:on_duplicate_key_update]
63
+ post_sql_statements << sql_for_on_duplicate_key_update( table_name, options[:on_duplicate_key_update] )
64
+ end
65
+ post_sql_statements
66
+ end
67
+
68
+
69
+ # Generates the INSERT statement used in insert multiple value sets.
70
+ def multiple_value_sets_insert_sql(table_name, column_names, options) # :nodoc:
71
+ "INSERT #{options[:ignore] ? 'IGNORE ':''}INTO #{table_name} (#{column_names.join(',')}) VALUES "
72
+ end
73
+
74
+ # Returns SQL the VALUES for an INSERT statement given the passed in +columns+
75
+ # and +array_of_attributes+.
76
+ def values_sql_for_column_names_and_attributes( columns, array_of_attributes ) # :nodoc:
77
+ values = []
78
+ array_of_attributes.each do |arr|
79
+ my_values = []
80
+ arr.each_with_index do |val,j|
81
+ my_values << quote( val, columns[j] )
82
+ end
83
+ values << my_values
84
+ end
85
+ values_arr = values.map{ |arr| '(' + arr.join( ',' ) + ')' }
86
+ end
87
+
55
88
  # Returns the sum of the sizes of the passed in objects. This should
56
89
  # probably be moved outside this class, but to where?
57
90
  def self.sum_sizes( *objects ) # :nodoc:
@@ -0,0 +1,8 @@
1
+ ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
2
+ # Returns the maximum number of bytes that the server will allow
3
+ # in a single packet
4
+ def max_allowed_packet # :nodoc:
5
+ result = execute( "SHOW VARIABLES like 'max_allowed_packet';" )
6
+ result.fetch_row[1].to_i
7
+ end
8
+ end
@@ -1,9 +1,14 @@
1
1
  module ActiveRecord # :nodoc:
2
2
  module ConnectionAdapters # :nodoc:
3
3
  class OracleAdapter # :nodoc:
4
- def supports_import?
5
- true
6
- end
4
+
5
+ def next_value_for_sequence(sequence_name)
6
+ %{#{sequence_name}.nextval}
7
+ end
8
+
9
+ def supports_import?
10
+ true
11
+ end
7
12
  end
8
13
  end
9
14
  end
@@ -1,7 +1,9 @@
1
1
  module ActiveRecord # :nodoc:
2
2
  module ConnectionAdapters # :nodoc:
3
3
  class PostgreSQLAdapter # :nodoc:
4
-
4
+ def next_value_for_sequence(sequence_name)
5
+ %{nextval('#{sequence_name}')}
6
+ end
5
7
  end
6
8
  end
7
9
  end
@@ -0,0 +1,7 @@
1
+ module ActiveRecord # :nodoc:
2
+ module ConnectionAdapters # :nodoc:
3
+ class SqliteAdapter # :nodoc:
4
+
5
+ end
6
+ end
7
+ end
@@ -1,6 +1,11 @@
1
+ begin
2
+ require 'faster_csv'
3
+ require 'ar-extensions/csv'
4
+ rescue LoadError => ex
5
+ STDERR.puts "FasterCSV is not installed. CSV functionality will not be included."
6
+ raise ex
7
+ end
1
8
 
2
- require 'faster_csv'
3
- require 'ostruct'
4
9
 
5
10
  # Adds CSV export options to ActiveRecord::Base models.
6
11
  #
@@ -46,7 +46,7 @@ require 'forwardable'
46
46
  # fieldname = caller.connection.quote_column_name( key )
47
47
  # min = caller.connection.quote( val.first, caller.columns_hash[ key ] )
48
48
  # max = caller.connection.quote( val.last, caller.columns_hash[ key ] )
49
- # str = "#{caller.table_name}.#{fieldname} #{match_data ? 'NOT ' : '' } BETWEEN #{min} AND #{max}"
49
+ # str = "#{caller.quoted_table_name}.#{fieldname} #{match_data ? 'NOT ' : '' } BETWEEN #{min} AND #{max}"
50
50
  # Result.new( str, nil )
51
51
  # end
52
52
  #
@@ -180,7 +180,7 @@ module ActiveRecord::Extensions
180
180
  if val.is_a?( Array )
181
181
  match_data = key.to_s.match( NOT_EQUAL_RGX )
182
182
  key = match_data.captures[0] if match_data
183
- str = "#{caller.table_name}.#{caller.connection.quote_column_name( key )} " +
183
+ str = "#{caller.quoted_table_name}.#{caller.connection.quote_column_name( key )} " +
184
184
  (match_data ? 'NOT ' : '') + "IN( ? )"
185
185
  return Result.new( str, val )
186
186
  end
@@ -206,6 +206,7 @@ module ActiveRecord::Extensions
206
206
  class Comparison
207
207
 
208
208
  SUFFIX_MAP = { 'eq'=>'=', 'lt'=>'<', 'lte'=>'<=', 'gt'=>'>', 'gte'=>'>=', 'ne'=>'!=', 'not'=>'!=' }
209
+ ACCEPTABLE_COMPARISONS = [ String, Numeric, Time, DateTime ]
209
210
 
210
211
  def self.process( key, val, caller )
211
212
  process_without_suffix( key, val, caller ) || process_with_suffix( key, val, caller )
@@ -214,21 +215,21 @@ module ActiveRecord::Extensions
214
215
  def self.process_without_suffix( key, val, caller )
215
216
  return nil unless caller.columns_hash.has_key?( key )
216
217
  if val.nil?
217
- str = "#{caller.table_name}.#{caller.connection.quote_column_name( key )} IS NULL"
218
+ str = "#{caller.quoted_table_name}.#{caller.connection.quote_column_name( key )} is ?"
218
219
  else
219
- str = "#{caller.table_name}.#{caller.connection.quote_column_name( key )}=?"
220
+ str = "#{caller.quoted_table_name}.#{caller.connection.quote_column_name( key )}=?"
220
221
  end
221
222
  Result.new( str, val )
222
223
  end
223
224
 
224
- def self.process_with_suffix( key, val, caller )
225
- return nil unless val.is_a?( String ) or val.is_a?( Numeric )
225
+ def self.process_with_suffix( key, val, caller )
226
+ return nil unless ACCEPTABLE_COMPARISONS.find{ |klass| val.is_a?(klass) }
226
227
  SUFFIX_MAP.each_pair do |k,v|
227
228
  match_data = key.to_s.match( /(.+)_#{k}$/ )
228
229
  if match_data
229
230
  fieldname = match_data.captures[0]
230
231
  return nil unless caller.columns_hash.has_key?( fieldname )
231
- str = "#{caller.table_name}.#{caller.connection.quote_column_name( fieldname )} " +
232
+ str = "#{caller.quoted_table_name}.#{caller.connection.quote_column_name( fieldname )} " +
232
233
  "#{v} #{caller.connection.quote( val, caller.columns_hash[ fieldname ] )} "
233
234
  return Result.new( str, nil )
234
235
  end
@@ -254,30 +255,35 @@ module ActiveRecord::Extensions
254
255
  LIKE_RGX = /(.+)_(like|contains)$/
255
256
  STARTS_WITH_RGX = /(.+)_starts_with$/
256
257
  ENDS_WITH_RGX = /(.+)_ends_with$/
257
-
258
258
  def self.process( key, val, caller )
259
259
  values = [*val]
260
260
  case key.to_s
261
261
  when LIKE_RGX
262
262
  str = values.collect do |v|
263
- "#{caller.table_name}.#{caller.connection.quote_column_name( $1 )} LIKE " +
263
+ "#{caller.quoted_table_name}.#{caller.connection.quote_column_name( $1 )} LIKE " +
264
264
  "#{caller.connection.quote( '%%' + v + '%%', caller.columns_hash[ $1 ] )} "
265
265
  end
266
266
  when STARTS_WITH_RGX
267
267
  str = values.collect do |v|
268
- "#{caller.table_name}.#{caller.connection.quote_column_name( $1 )} LIKE " +
268
+ "#{caller.quoted_table_name}.#{caller.connection.quote_column_name( $1 )} LIKE " +
269
269
  "#{caller.connection.quote( v + '%%', caller.columns_hash[ $1 ] )} "
270
270
  end
271
271
  when ENDS_WITH_RGX
272
272
  str = values.collect do |v|
273
- "#{caller.table_name}.#{caller.connection.quote_column_name( $1 )} LIKE " +
273
+ "#{caller.quoted_table_name}.#{caller.connection.quote_column_name( $1 )} LIKE " +
274
274
  "#{caller.connection.quote( '%%' + v, caller.columns_hash[ $1 ] )} "
275
275
  end
276
276
  else
277
277
  return nil
278
278
  end
279
279
 
280
- return Result.new( str.join(' OR '), nil)
280
+ str = str.join(' OR ')
281
+ result_values = []
282
+ str.gsub!(/'((%%)?([^\?]*\?[^%]*|[^%]*%[^%]*)(%%)?)'/) do |match|
283
+ result_values << $2
284
+ '?'
285
+ end
286
+ return Result.new(str , result_values)
281
287
  end
282
288
  end
283
289
 
@@ -308,7 +314,7 @@ module ActiveRecord::Extensions
308
314
  fieldname = caller.connection.quote_column_name( key )
309
315
  min = caller.connection.quote( val.first, caller.columns_hash[ key ] )
310
316
  max = caller.connection.quote( val.last, caller.columns_hash[ key ] )
311
- str = "#{caller.table_name}.#{fieldname} #{match_data ? 'NOT ' : '' } BETWEEN #{min} AND #{max}"
317
+ str = "#{caller.quoted_table_name}.#{fieldname} #{match_data ? 'NOT ' : '' } BETWEEN #{min} AND #{max}"
312
318
  return Result.new( str, nil )
313
319
  end
314
320
  nil
@@ -375,7 +381,7 @@ module ActiveRecord::Extensions
375
381
  def self.process( key, val, caller )
376
382
  return nil unless val.is_a?( Regexp )
377
383
  r = field_result( key, caller )
378
- Result.new( "#{caller.table_name}.#{r.fieldname} #{r.negate? ? 'NOT ':''} REGEXP ?", val )
384
+ Result.new( "#{caller.quoted_table_name}.#{r.fieldname} #{r.negate? ? 'NOT ':''} REGEXP ?", val )
379
385
  end
380
386
 
381
387
  end
@@ -390,7 +396,7 @@ module ActiveRecord::Extensions
390
396
  def self.process( key, val, caller )
391
397
  return nil unless val.is_a?( Regexp )
392
398
  r = field_result( key, caller )
393
- return Result.new( "#{caller.table_name}.#{r.fieldname} #{r.negate? ? '!~ ':'~'} ?", val )
399
+ return Result.new( "#{caller.quoted_table_name}.#{r.fieldname} #{r.negate? ? '!~ ':'~'} ?", val )
394
400
  end
395
401
 
396
402
  end
@@ -403,7 +409,7 @@ module ActiveRecord::Extensions
403
409
  def self.process( key, val, caller )
404
410
  return nil unless val.is_a?( Regexp )
405
411
  r = field_result( key, caller )
406
- return Result.new( "#{r.negate? ? ' NOT ':''} REGEXP_LIKE(#{caller.table_name}.#{r.fieldname} , ?)", val )
412
+ return Result.new( "#{r.negate? ? ' NOT ':''} REGEXP_LIKE(#{caller.quoted_table_name}.#{r.fieldname} , ?)", val )
407
413
  end
408
414
 
409
415
  end
@@ -453,9 +459,9 @@ module ActiveRecord::Extensions
453
459
  def self.process_without_suffix( key, val, caller )
454
460
  return nil unless caller.columns_hash.has_key?( key )
455
461
  if val.nil?
456
- str = "#{caller.table_name}.#{caller.connection.quote_column_name( key )} IS NULL"
462
+ str = "#{caller.quoted_table_name}.#{caller.connection.quote_column_name( key )} IS NULL"
457
463
  else
458
- str = "#{caller.table_name}.#{caller.connection.quote_column_name( key )}=" +
464
+ str = "#{caller.quoted_table_name}.#{caller.connection.quote_column_name( key )}=" +
459
465
  "#{caller.connection.quote( val.to_s(:db), caller.columns_hash[ key ] )} "
460
466
  end
461
467
  Result.new( str, nil )
@@ -467,7 +473,7 @@ module ActiveRecord::Extensions
467
473
  if match_data
468
474
  fieldname = match_data.captures[0]
469
475
  return nil unless caller.columns_hash.has_key?( fieldname )
470
- str = "#{caller.table_name}.#{caller.connection.quote_column_name( fieldname )} " +
476
+ str = "#{caller.quoted_table_name}.#{caller.connection.quote_column_name( fieldname )} " +
471
477
  "#{v} #{caller.connection.quote( val.to_s(:db), caller.columns_hash[ fieldname ] )} "
472
478
  return Result.new( str, nil )
473
479
  end
@@ -19,7 +19,7 @@ class ActiveRecord::Base
19
19
 
20
20
  alias :sanitize_sql_orig :sanitize_sql
21
21
  def sanitize_sql( arg ) # :nodoc:
22
- return sanitize_sql_orig( arg ) if arg.nil?
22
+ return if arg.blank? # don't process arguments like [], {}, "" or nil
23
23
  if arg.respond_to?( :to_sql )
24
24
  arg = sanitize_sql_by_way_of_duck_typing( arg )
25
25
  elsif arg.is_a?( Hash )
@@ -35,7 +35,8 @@ class ActiveRecord::Base
35
35
  end
36
36
 
37
37
  def sanitize_sql_from_string_and_hash( arr ) # :nodoc:
38
- return arr if arr.first =~ /\:[\w]+/
38
+ return arr if arr.first =~ /\:[\w]+/
39
+ return arr if arr.last.empty? # skip empty hash conditions, ie: :conditions => ["", {}]
39
40
  arr2 = sanitize_sql_from_hash( arr.last )
40
41
  if arr2.empty?
41
42
  conditions = arr.first
@@ -48,7 +49,8 @@ class ActiveRecord::Base
48
49
 
49
50
  def sanitize_sql_from_hash( hsh ) #:nodoc:
50
51
  conditions, values = [], []
51
-
52
+ hsh = expand_hash_conditions_for_aggregates(hsh) # introduced in Rails 2.0.2
53
+
52
54
  hsh.each_pair do |key,val|
53
55
  if val.respond_to?( :to_sql )
54
56
  conditions << sanitize_sql_by_way_of_duck_typing( val )
@@ -57,10 +59,19 @@ class ActiveRecord::Base
57
59
  sql = nil
58
60
  result = ActiveRecord::Extensions.process( key, val, self )
59
61
  if result
60
- conditions << result.sql if result.sql
61
- values.push( result.value ) if result.value
62
+ conditions << result.sql
63
+ values.push( result.value )
62
64
  else
63
- conditions << "#{table_name}.#{connection.quote_column_name(key.to_s)} #{attribute_condition( val )} "
65
+ # Extract table name from qualified attribute names.
66
+ attr = key.to_s
67
+ if attr.include?('.')
68
+ table_name, attr = attr.split('.', 2)
69
+ table_name = connection.quote_table_name(table_name)
70
+ else
71
+ table_name = quoted_table_name
72
+ end
73
+
74
+ conditions << "#{table_name}.#{connection.quote_column_name(attr)} #{attribute_condition( val )} "
64
75
  values << val
65
76
  end
66
77
  end
@@ -51,7 +51,6 @@ class ActiveRecord::Base
51
51
  rescue NoMethodError
52
52
  false
53
53
  end
54
-
55
54
  end
56
55
 
57
56
  end
@@ -35,7 +35,7 @@ class ActiveRecord::Extensions::FullTextSearching::MySQLFullTextExtension
35
35
  end
36
36
  ActiveRecord::Extensions.register ActiveRecord::Extensions::FullTextSearching::MySQLFullTextExtension.new, :adapters=>[:mysql]
37
37
 
38
- class ActiveRecord::ConnectionAdapters::MysqlAdapter # :nodoc:
38
+ ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
39
39
  include ActiveRecord::Extensions::FullTextSearching::FullTextSupport
40
40
 
41
41
  def register_fulltext_extension( fulltext_key, options ) # :nodoc:
@@ -262,29 +262,29 @@ class ActiveRecord::Base
262
262
  array_of_attributes.each do |arr|
263
263
  my_values = []
264
264
  arr.each_with_index do |val,j|
265
- if sequence_name && column_names[j] == primary_key && val.nil?
266
- my_values << "#{sequence_name}.nextval"
265
+ if !sequence_name.blank? && column_names[j] == primary_key && val.nil?
266
+ my_values << connection.next_value_for_sequence(sequence_name)
267
267
  else
268
268
  my_values << connection.quote( val, columns[j] )
269
269
  end
270
270
  end
271
- insert_statements << "INSERT INTO #{self.table_name} #{columns_sql} VALUES(" + my_values.join( ',' ) + ")"
272
- number_inserted = number_inserted + connection.execute( insert_statements.last )
271
+ insert_statements << "INSERT INTO #{quoted_table_name} #{columns_sql} VALUES(" + my_values.join( ',' ) + ")"
272
+ connection.execute( insert_statements.last )
273
+ number_inserted += 1
273
274
  end
274
- return number_inserted
275
275
  else
276
-
277
276
  # generate the sql
278
- insert_sql = connection.multiple_value_sets_insert_sql( table_name, escaped_column_names, options )
277
+ insert_sql = connection.multiple_value_sets_insert_sql( quoted_table_name, escaped_column_names, options )
279
278
  values_sql = connection.values_sql_for_column_names_and_attributes( columns, array_of_attributes )
280
- post_sql_statements = connection.post_sql_statements( table_name, options )
279
+ post_sql_statements = connection.post_sql_statements( quoted_table_name, options )
281
280
 
282
281
  # perform the inserts
283
- number_of_inserts = connection.insert_many(
284
- [ insert_sql, post_sql_statements ].flatten,
285
- values_sql,
286
- "#{self.class.name} Create Many Without Validations Or Callbacks" )
282
+ number_inserted = connection.insert_many( [ insert_sql, post_sql_statements ].flatten,
283
+ values_sql,
284
+ "#{self.class.name} Create Many Without Validations Or Callbacks" )
287
285
  end
286
+
287
+ number_inserted
288
288
  end
289
289
 
290
290
  # Returns an array of quoted column names
@@ -2,20 +2,7 @@ module ActiveRecord::Extensions::ConnectionAdapters::MysqlAdapter # :nodoc:
2
2
 
3
3
  include ActiveRecord::Extensions::Import::ImportSupport
4
4
  include ActiveRecord::Extensions::Import::OnDuplicateKeyUpdateSupport
5
-
6
- # Returns an array of post SQL statements given the passed in options.
7
- def post_sql_statements( table_name, options ) # :nodoc:
8
- post_sql_statements = []
9
- if options[:on_duplicate_key_update]
10
- post_sql_statements << sql_for_on_duplicate_key_update( table_name, options[:on_duplicate_key_update] )
11
- end
12
- post_sql_statements
13
- end
14
-
15
- def multiple_value_sets_insert_sql( table_name, column_names, options ) # :nodoc:
16
- "INSERT #{options[:ignore] ? 'IGNORE ':''} INTO #{table_name} (#{column_names.join(',')}) VALUES "
17
- end
18
-
5
+
19
6
  # Returns a generated ON DUPLICATE KEY UPDATE statement given the passed
20
7
  # in +args+.
21
8
  def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc:
@@ -32,39 +19,25 @@ module ActiveRecord::Extensions::ConnectionAdapters::MysqlAdapter # :nodoc:
32
19
  end
33
20
 
34
21
  def sql_for_on_duplicate_key_update_as_array( table_name, arr ) # :nodoc:
35
- qt = quote_column_name( table_name )
36
22
  results = arr.map do |column|
37
23
  qc = quote_column_name( column )
38
- "#{qt}.#{qc}=VALUES(#{qc})"
24
+ "#{table_name}.#{qc}=VALUES(#{qc})"
39
25
  end
40
26
  results.join( ',' )
41
27
  end
42
28
 
43
29
  def sql_for_on_duplicate_key_update_as_hash( table_name, hsh ) # :nodoc:
44
30
  sql = ' ON DUPLICATE KEY UPDATE '
45
- qt = quote_column_name( table_name )
46
31
  results = hsh.map do |column1, column2|
47
32
  qc1 = quote_column_name( column1 )
48
33
  qc2 = quote_column_name( column2 )
49
- "#{qt}.#{qc1}=VALUES( #{qc2} )"
34
+ "#{table_name}.#{qc1}=VALUES( #{qc2} )"
50
35
  end
51
36
  results.join( ',')
52
37
  end
53
38
 
54
- # Returns SQL the VALUES for an INSERT statement given the passed in +columns+
55
- # and +array_of_attributes+.
56
- def values_sql_for_column_names_and_attributes( columns, array_of_attributes ) # :nodoc:
57
- values = []
58
- array_of_attributes.each do |arr|
59
- my_values = []
60
- arr.each_with_index do |val,j|
61
- my_values << quote( val, columns[j] )
62
- end
63
- values << my_values
64
- end
65
- values_arr = values.map{ |arr| '(' + arr.join( ',' ) + ')' }
66
- end
67
-
68
39
  end
69
40
 
70
- ActiveRecord::ConnectionAdapters::MysqlAdapter.send( 'include', ActiveRecord::Extensions::ConnectionAdapters::MysqlAdapter )
41
+ ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
42
+ include ActiveRecord::Extensions::ConnectionAdapters::MysqlAdapter
43
+ end
@@ -0,0 +1,22 @@
1
+ module ActiveRecord::Extensions::ConnectionAdapters::SQLiteAdapter # :nodoc:
2
+ include ActiveRecord::Extensions::Import::ImportSupport
3
+
4
+ def post_sql_statements( table_name, options )
5
+ []
6
+ end
7
+
8
+ def insert_many( sql, values, *args ) # :nodoc:
9
+ sql2insert = []
10
+ values.each do |value|
11
+ sql2insert << "#{sql} #{value};"
12
+ end
13
+
14
+ raw_connection.transaction { |db| db.execute_batch(sql2insert.join("\n")) }
15
+ number_of_rows_inserted = sql2insert.size
16
+ end
17
+
18
+ end
19
+
20
+ ActiveRecord::ConnectionAdapters::SQLiteAdapter.class_eval do
21
+ include ActiveRecord::Extensions::ConnectionAdapters::SQLiteAdapter
22
+ end
@@ -8,7 +8,7 @@ module ActiveRecord # :nodoc:
8
8
  #
9
9
  # This uses one query for all instance updates and then updates existing
10
10
  # instances rather sending one query for each instance
11
- def self.synchronize(instances, key=ActiveRecord::Base.primary_key)
11
+ def self.synchronize(instances, key=self.primary_key)
12
12
  return if instances.empty?
13
13
 
14
14
  keys = instances.map(&"#{key}".to_sym)
@@ -87,7 +87,6 @@ class ActiveRecord::Base
87
87
  end"
88
88
 
89
89
  @@temporary_table_hsh[ model = Object.const_get( model_name ) ] = true
90
-
91
90
  if block_given?
92
91
  yield model
93
92
  model.drop
@@ -1,3 +1,3 @@
1
- class ActiveRecord::ConnectionAdapters::MysqlAdapter # :nodoc:
1
+ ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
2
2
  include ActiveRecord::Extensions::TemporaryTableSupport
3
3
  end
metadata CHANGED
@@ -1,39 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.2
3
- specification_version: 1
4
2
  name: ar-extensions
5
3
  version: !ruby/object:Gem::Version
6
- version: 0.7.0
7
- date: 2007-07-21 00:00:00 -04:00
8
- summary: Extends ActiveRecord functionality.
9
- require_paths:
10
- - lib
11
- email: zach.dennis@gmail.com
12
- homepage: http://www.continuousthinking.com/tags/arext
13
- rubyforge_project: arext
14
- description: Extends ActiveRecord functionality by adding better finder/query support, as well as supporting mass data import, foreign key, CSV and temporary tables
15
- autorequire: ar-extensions.rb
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: true
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
24
- version:
4
+ version: 0.8.0
25
5
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
6
  authors:
30
7
  - Zach Dennis
31
8
  - Mark Van Holstyn
9
+ autorequire: ar-extensions.rb
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2008-08-06 00:00:00 -04:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: activerecord
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.14.1
24
+ version:
25
+ description: Extends ActiveRecord functionality by adding better finder/query support, as well as supporting mass data import, foreign key, CSV and temporary tables
26
+ email: zach.dennis@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
32
33
  files:
33
34
  - init.rb
34
35
  - db/migrate
35
36
  - db/migrate/generic_schema.rb
36
37
  - db/migrate/mysql_schema.rb
38
+ - db/migrate/oracle_schema.rb
37
39
  - db/migrate/version.rb
38
40
  - Rakefile
39
41
  - ChangeLog
@@ -43,9 +45,10 @@ files:
43
45
  - config/mysql.schema
44
46
  - config/postgresql.schema
45
47
  - lib/ar-extensions/adapters/abstract_adapter.rb
46
- - lib/ar-extensions/adapters/mysql_adapter.rb
48
+ - lib/ar-extensions/adapters/mysql.rb
47
49
  - lib/ar-extensions/adapters/oracle.rb
48
50
  - lib/ar-extensions/adapters/postgresql.rb
51
+ - lib/ar-extensions/adapters/sqlite.rb
49
52
  - lib/ar-extensions/csv.rb
50
53
  - lib/ar-extensions/extensions.rb
51
54
  - lib/ar-extensions/finders.rb
@@ -54,32 +57,39 @@ files:
54
57
  - lib/ar-extensions/fulltext.rb
55
58
  - lib/ar-extensions/import/mysql.rb
56
59
  - lib/ar-extensions/import/postgresql.rb
60
+ - lib/ar-extensions/import/sqlite.rb
57
61
  - lib/ar-extensions/import.rb
58
62
  - lib/ar-extensions/synchronize.rb
59
63
  - lib/ar-extensions/temporary_table/mysql.rb
60
64
  - lib/ar-extensions/temporary_table.rb
61
65
  - lib/ar-extensions/version.rb
62
66
  - lib/ar-extensions.rb
63
- test_files: []
64
-
67
+ has_rdoc: true
68
+ homepage: http://www.continuousthinking.com/tags/arext
69
+ post_install_message:
65
70
  rdoc_options:
66
71
  - --main
67
72
  - README
68
- extra_rdoc_files:
69
- - README
70
- executables: []
71
-
72
- extensions: []
73
-
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ version:
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ version:
74
87
  requirements: []
75
88
 
76
- dependencies:
77
- - !ruby/object:Gem::Dependency
78
- name: activerecord
79
- version_requirement:
80
- version_requirements: !ruby/object:Gem::Version::Requirement
81
- requirements:
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- version: 1.14.1
85
- version:
89
+ rubyforge_project: arext
90
+ rubygems_version: 1.1.0
91
+ signing_key:
92
+ specification_version: 2
93
+ summary: Extends ActiveRecord functionality.
94
+ test_files: []
95
+
@@ -1,14 +0,0 @@
1
- module ActiveRecord # :nodoc:
2
- module ConnectionAdapters # :nodoc:
3
- class MysqlAdapter # :nodoc:
4
-
5
- # Returns the maximum number of bytes that the server will allow
6
- # in a single packet
7
- def max_allowed_packet # :nodoc:
8
- result = execute( "SHOW VARIABLES like 'max_allowed_packet';" )
9
- result.fetch_row[1].to_i
10
- end
11
-
12
- end #end MysqlAdapter
13
- end #end ConnectionAdapters
14
- end #end ActiveRecord