Class: ActiveRecord::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record/connection_adapters/ibm_db_pstmt.rb,
lib/active_record/connection_adapters/ibm_db_adapter.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.add_conditions!(sql, conditions, scope = :auto) ⇒ Object

Adds a sanitized version of conditions to the sql string. Note that the passed-in sql string is changed. The optional scope argument is for the current :find scope.



636
637
638
639
640
641
642
643
644
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 636

def add_conditions!(sql, conditions, scope = :auto)
  scope = scope(:find) if :auto == scope
  conditions = [conditions]
  conditions << scope[:conditions] if scope
  conditions << type_condition if finder_needs_type_condition?
  merged_conditions = merge_conditions(*conditions)
  sql << "WHERE #{merged_conditions["sqlSegment"]} " unless merged_conditions["sqlSegment"].blank?
  merged_conditions["paramArray"]
end

.add_group!(sql, group, having, scope = :auto) ⇒ Object



404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 404

def add_group!(sql, group, having, scope = :auto)
  param_array = []
  if group
    sql << " GROUP BY #{group}"
    if having
      sql_param_hash = sanitize_sql_for_conditions(having)
      sql << " HAVING #{sql_param_hash["sqlSegment"]}"
      param_array = param_array + sql_param_hash["paramArray"] unless sql_param_hash["paramArray"].nil?
    end
  else
    scope = scope(:find) if :auto == scope
    if scope && (scoped_group = scope[:group])
      sql << " GROUP BY #{scoped_group}"
      if scope[:having]
        sql_param_hash = sanitize_sql_for_conditions(scope[:having])
        sql << " HAVING #{sql_param_hash["sqlSegment"]}"
        param_array = param_array + sql_param_hash["paramArray"] unless sql_param_hash["paramArray"].nil?
      end
    end
  end
  param_array
end

.add_joins!(sql, joins, scope = :auto) ⇒ Object

The optional scope argument is for the current :find scope.



428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 428

def add_joins!(sql, joins, scope = :auto)
  param_array = []
  scope = scope(:find) if :auto == scope

  if joins.is_a?(Hash) && joins.has_key?("pstmt_hook")
    param_array = joins["pstmt_hook"]["paramArray"]
    joins = joins["pstmt_hook"]["sqlSegment"]
  end

  merged_joins = if scope && scope[:joins] && joins 
                   join_merge_hash = merge_joins(scope[:joins], joins)
                   param_array = param_array + join_merge_hash["pstmt_hook"]["paramArray"]
                   join_merge_hash["pstmt_hook"]["sqlSegment"]
                 else
                   if(scope && scope[:joins].is_a?(Hash) && scope[:joins].has_key?("pstmt_hook"))
                     param_array = scope[:joins]["pstmt_hook"]["paramArray"]
                     (joins || scope[:joins]["pstmt_hook"]["sqlSegment"])
                   else
                     (joins || scope && scope[:joins])
                   end
                 end

  case merged_joins
  when Symbol, Hash, Array
    if array_of_strings?(merged_joins)
      sql << merged_joins.join(' ') + " "
    else
      join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, merged_joins, nil)
      sql << " #{join_dependency.join_associations.collect { |assoc| 
                    sql_param_hash = assoc.association_join 
                    param_array = param_array + sql_param_hash["paramArray"] unless sql_param_hash["paramArray"].nil?
                    sql_param_hash["sqlSegment"]
                  }.join} "
    end
  when String
    sql << " #{merged_joins} "
  end
  param_array
end

.attribute_condition(quoted_column_name, argument) ⇒ Object



659
660
661
662
663
664
665
666
667
668
669
670
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 659

def attribute_condition(quoted_column_name, argument)
  case argument
    when nil   then "#{quoted_column_name} IS NULL"
    when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::NamedScope::Scope then "#{quoted_column_name} IN (?)"
    when Range then if argument.exclude_end?
                      "#{quoted_column_name} >= ? AND #{quoted_column_name} < ?"
                    else
                      "#{quoted_column_name} BETWEEN ? AND ?"
                    end
    else            "#{quoted_column_name} = ?"
  end
end

.construct_finder_sql(options) ⇒ Object



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 379

def construct_finder_sql(options)
  param_array = []
  scope = scope(:find)
  sql  = "SELECT #{options[:select] || (scope && scope[:select]) || default_select(options[:joins] || (scope && scope[:joins]))} "
  sql << "FROM #{options[:from]  || (scope && scope[:from]) || quoted_table_name} "

  param_array = add_joins!(sql, options[:joins], scope)

  param_array = param_array + add_conditions!(sql, options[:conditions], scope)

  param_array = param_array + add_group!(sql, options[:group], options[:having], scope)

  add_order!(sql, options[:order], scope)

  temp_options = options.dup # Ensure that the necessary parameters are received in the duplicate, so that the original hash is intact
  temp_options[:paramArray] = [] # To receive the values for limit and offset.
  add_limit!(sql, temp_options, scope)

  param_array = param_array + temp_options[:paramArray]

  add_lock!(sql, options, scope)

  [sql] + param_array
end

.count_by_sql(sql) ⇒ Object



532
533
534
535
536
537
538
539
540
541
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 532

def count_by_sql(sql)
  sql_param_hash = sanitize_conditions(sql)
  result = connection.prepared_select(sql_param_hash, "#{name} Count").first
  #result will be of type Hash.
  if result
    return result.values.first.to_i  #Retrieve the first value from hash
  else
    return 0
  end
end

.delete_all(conditions = nil) ⇒ Object



603
604
605
606
607
608
609
610
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 603

def delete_all(conditions = nil)
  sql = "DELETE FROM #{quoted_table_name} "
  param_array = add_conditions!(sql, conditions, scope(:find))
  # Prepare the sql for deleting the rows
  pstmt = connection.prepare(sql, "#{name} Delete all")
  # Execute the prepared Statement
  connection.prepared_delete(pstmt, param_array)
end

.expand_id_conditions(id_or_conditions) ⇒ Object

Interpret Array and Hash as conditions and anything else as an id.



372
373
374
375
376
377
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 372

def expand_id_conditions(id_or_conditions)
  case id_or_conditions
    when Array, Hash then id_or_conditions
    else {primary_key => id_or_conditions}
  end
end

.find_by_sql(sql) ⇒ Object



366
367
368
369
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 366

def find_by_sql(sql)
  sql_param_hash = sanitize_sql(sql)
  connection.prepared_select(sql_param_hash, "#{name} Load").collect! { |record| instantiate(record) }
end

.find_one(id, options) ⇒ Object



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 253

def find_one(id, options)
  param_array = [quote_value(id,columns_hash[primary_key])]
  if options[:conditions]
    sql_param_hash = sanitize_sql(options[:conditions])
    conditions = " AND (#{sql_param_hash["sqlSegment"]})"
    param_array = param_array + sql_param_hash["paramArray"] unless sql_param_hash["paramArray"].nil?
  end

  options.update :conditions => ["#{quoted_table_name}.#{connection.quote_column_name(primary_key)} = ?#{conditions}"] + param_array

  # Use find_every(options).first since the primary key condition
  # already ensures we have a single record. Using find_initial adds
  # a superfluous :limit => 1.
  if result = find_every(options).first
    result
  else
    raise RecordNotFound, "Couldn't find #{name} with ID=#{id}#{conditions} with parameters #{param_array.last(param_array.size-1)}"
  end
end

.find_some(ids, options) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 273

def find_some(ids, options)
  param_array = []
  ids_array = ids.map { |id| quote_value(id,columns_hash[primary_key]) }
  if options[:conditions]
    sql_param_hash = sanitize_sql(options[:conditions])
    conditions = " AND (#{sql_param_hash["sqlSegment"]})"
    param_array = param_array + sql_param_hash["paramArray"] unless sql_param_hash["paramArray"].nil?
  end

  options.update :conditions => ["#{quoted_table_name}.#{connection.quote_column_name(primary_key)} IN (?)#{conditions}"] + [ids_array] + param_array

  result = find_every(options)

  # Determine expected size from limit and offset, not just ids.size.
  expected_size =
    if options[:limit] && ids.size > options[:limit]
      options[:limit]
    else
      ids.size
    end

  # 11 ids with limit 3, offset 9 should give 2 results.
  if options[:offset] && (ids.size - options[:offset] < expected_size)
    expected_size = ids.size - options[:offset]
  end

  if result.size == expected_size
    result
  else
    raise RecordNotFound, "Couldn't find all #{name.pluralize} with IDs (#{ids.join(', ')})#{conditions} with parameter(s) #{param_array.join(', ')} (found #{result.size} results, but was looking for #{expected_size})"
  end
end

.ibm_db_connection(config) ⇒ Object

Establishes a connection to a specified database using the credentials provided with the config argument. All the ActiveRecord objects will use this connection



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/active_record/connection_adapters/ibm_db_adapter.rb', line 153

def self.ibm_db_connection(config)
  # Attempts to load the Ruby driver IBM databases
  # while not already loaded or raises LoadError in case of failure.
  begin
    require 'ibm_db' unless defined? IBM_DB
  rescue LoadError
    raise LoadError, "Failed to load IBM_DB Ruby driver."
  end

  #if( config.has_key?(:parameterized) && config[:parameterized] == true )
  #  require 'active_record/connection_adapters/ibm_db_pstmt'
  #end

	  # Check if class TableDefinition responds to indexes method to determine if we are on AR 3 or AR 4.
	  # This is a interim hack ti ensure backward compatibility. To remove as we move out of AR 3 support or have a better way to determine which version of AR being run against.
	  checkClass = ActiveRecord::ConnectionAdapters::TableDefinition.new(nil)
	  if(checkClass.respond_to?(:indexes))
 isAr3 = false
	  else
 isAr3 = true
	  end
  # Converts all +config+ keys to symbols
  config = config.symbolize_keys

  # Flag to decide if quoted literal replcement should take place. By default it is ON. Set it to OFF if using Pstmt
  set_quoted_literal_replacement = IBM_DB::QUOTED_LITERAL_REPLACEMENT_ON

  # Retrieves database user credentials from the +config+ hash
  # or raises ArgumentError in case of failure.
  if !config.has_key?(:username) || !config.has_key?(:password)
    raise ArgumentError, "Missing argument(s): Username/Password for #{config[:database]} is not specified"
  else
    if(config[:username].to_s.nil? || config[:password].to_s.nil?)
      raise ArgumentError, "Username/Password cannot be nil"
    end
    username = config[:username].to_s
    password = config[:password].to_s
  end

  if(config.has_key?(:dbops) && config[:dbops] == true)
    return ConnectionAdapters::IBM_DBAdapter.new(nil, isAr3, logger, config, {})
  end

  # Retrieves the database alias (local catalog name) or remote name
  # (for remote TCP/IP connections) from the +config+ hash
  # or raises ArgumentError in case of failure.
  if config.has_key?(:database)
    database = config[:database].to_s
  else
    raise ArgumentError, "Missing argument: a database name needs to be specified."
  end

  # Providing default schema (username) when not specified
  config[:schema] = config.has_key?(:schema) ? config[:schema].to_s : config[:username].to_s

  if(config.has_key?(:parameterized) && config[:parameterized] == true )
    set_quoted_literal_replacement = IBM_DB::QUOTED_LITERAL_REPLACEMENT_OFF
  end

  # Extract connection options from the database configuration
  # (in support to formatting, audit and billing purposes):
  # Retrieve database objects fields in lowercase
  conn_options = {IBM_DB::ATTR_CASE => IBM_DB::CASE_LOWER}
  config.each do |key, value|
    if !value.nil?
      case key
        when :app_user        # Set connection's user info
          conn_options[IBM_DB::SQL_ATTR_INFO_USERID]     = value
        when :account         # Set connection's account info
          conn_options[IBM_DB::SQL_ATTR_INFO_ACCTSTR]    = value
        when :application     # Set connection's application info
          conn_options[IBM_DB::SQL_ATTR_INFO_APPLNAME]   = value
        when :workstation     # Set connection's workstation info
          conn_options[IBM_DB::SQL_ATTR_INFO_WRKSTNNAME] = value
      end    
    end
  end

  begin
    # Checks if a host name or address has been specified. If so, this implies a TCP/IP connection
    # Returns IBM_DB.Connection object upon succesful DB connection to the database
    # If otherwise the connection fails, +false+ is returned
    if config.has_key?(:host)
      # Retrieves the host address/name
      host = config[:host]
      # A net address connection requires a port. If no port has been specified, 50000 is used by default
      port = config[:port] || 50000
      # Connects to the database specified using the hostname, port, authentication type, username and password info
      # Starting with DB2 9.1FP5 secure connections using SSL are supported. 
      # On the client side using CLI this is supported from CLI version V95FP2 and onwards.
      # This feature is set by specifying SECURITY=SSL in the connection string.
      # Below connection string is constructed and SECURITY parameter is appended if the user has specified the :security option
      conn_string = "DRIVER={IBM DB2 ODBC DRIVER};\
                     DATABASE=#{database};\
                     HOSTNAME=#{host};\
                     PORT=#{port};\
                     PROTOCOL=TCPIP;\
                     UID=#{username};\
                     PWD=#{password};"
      conn_string << "SECURITY=#{config[:security]};" if config.has_key?(:security)
      conn_string << "AUTHENTICATION=#{config[:authentication]};" if config.has_key?(:authentication)
      conn_string << "CONNECTTIMEOUT=#{config[:timeout]};" if config.has_key?(:timeout)
    
      connection = IBM_DB.connect( conn_string, '', '', conn_options, set_quoted_literal_replacement )
    else
      # No host implies a local catalog-based connection: +database+ represents catalog alias
      connection = IBM_DB.connect( database, username, password, conn_options,  set_quoted_literal_replacement )
    end
  rescue StandardError => connect_err
    raise "Failed to connect to [#{database}] due to: #{connect_err}"
  end
  # Verifies that the connection was successful
  if connection
    # Creates an instance of *IBM_DBAdapter* based on the +connection+
    # and credentials provided in +config+
    ConnectionAdapters::IBM_DBAdapter.new(connection, isAr3, logger, config, conn_options)
  else
    # If the connection failure was not caught previoulsy, it raises a Runtime error
    raise "An unexpected error occured during connect attempt to [#{database}]"
  end
end

.ibmdb_connection(config) ⇒ Object

method self.ibm_db_connection



275
276
277
278
# File 'lib/active_record/connection_adapters/ibm_db_adapter.rb', line 275

def self.ibmdb_connection(config)
	  #Method to support alising of adapter name as ibmdb [without underscore]
  self.ibm_db_connection(config)
end

.merge_conditions(*conditions) ⇒ Object

Merges conditions so that the result is a valid condition



613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 613

def merge_conditions(*conditions)
  segments = []
  return_hash = {}
  return_hash["paramArray"] = []
  conditions.each do |condition|
    unless condition.blank?
      sql_param_hash = sanitize_sql(condition)
      unless sql_param_hash["sqlSegment"].blank?
        segments << sql_param_hash["sqlSegment"]
        if !sql_param_hash["paramArray"].nil? && !sql_param_hash["paramArray"].empty?
          return_hash["paramArray"] = return_hash["paramArray"] + 
                                      sql_param_hash["paramArray"]
        end
      end
    end
  end

  return_hash["sqlSegment"] = "(#{segments.join(') AND (')})" unless segments.empty?
  return_hash
end

.merge_joins(*joins) ⇒ Object



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 306

def merge_joins(*joins)
  sql_param_hash = {}
  param_array = []
  if joins.any?{|j| j.is_a?(String) || array_of_strings?(j) || (j.is_a?(Hash) && j.has_key?("pstmt_hook"))}
    joins_array = []
    joins_compare_array = []

    joins.each do |join|
      get_join_associations = true
      if join.is_a?(String)
        unless joins_compare_array.include?(join)
          joins_array << join
          joins_compare_array << join
        end
        get_join_associations = false
      elsif (join.is_a?(Hash) && join.has_key?("pstmt_hook"))
        if(join["pstmt_hook"]["sqlSegment"].is_a?(Array))
          compare_string = join["pstmt_hook"]["sqlSegment"].join(" ") + join["pstmt_hook"]["paramArray"].join(" ")
        else
          compare_string = join["pstmt_hook"]["sqlSegment"] + join["pstmt_hook"]["paramArray"].join(" ")
        end
        unless joins_compare_array.include?(compare_string)
          param_array = param_array + join["pstmt_hook"]["paramArray"] unless join["pstmt_hook"]["paramArray"].nil?
          joins_array << join["pstmt_hook"]["sqlSegment"]
          joins_compare_array << compare_string
        end
        get_join_associations = false
      end
      unless array_of_strings?(join)
        if get_join_associations
          join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, join, nil)
          join_dependency.join_associations.each do |assoc| 
            sql_param_hash = assoc.association_join
            compare_string = nil
            compare_string = sql_param_hash["sqlSegment"] + sql_param_hash["paramArray"].join(" ") unless sql_param_hash.nil?
            unless compare_string.nil? || joins_array.include?(compare_string)
              param_array = param_array + sql_param_hash["paramArray"] unless sql_param_hash["paramArray"].nil?
              joins_array << sql_param_hash["sqlSegment"]
              joins_compare_array << compare_string
            end
          end
        end
      else
        if get_join_associations
          joins_array = joins_array + join.flatten.map{|j| j.strip }.uniq
        end
      end
    end
    sql_param_hash["sqlSegment"] = joins_array.flatten.map{|j| j.strip }.uniq
    sql_param_hash["paramArray"] = param_array
    {"pstmt_hook" => sql_param_hash}
  else
    sql_param_hash["sqlSegment"] = joins.collect{|j| safe_to_array(j)}.flatten.uniq
    sql_param_hash["paramArray"] = param_array
    {"pstmt_hook" => sql_param_hash}
  end
end

.quote_bound_value(value) ⇒ Object

Returns an array of parameter values, with the values respectively quoted if of type date time or is nil



830
831
832
833
834
835
836
837
838
839
840
841
842
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 830

def quote_bound_value(value) #:nodoc:
  if value.respond_to?(:map) && !value.acts_like?(:string)
    if (value.respond_to?(:empty?) && value.empty?) || value.nil?
      [nil]
    else
      value.map { |v| 
          connection.quote_value_for_pstmt(v)
      }
    end
  else
    [connection.quote_value_for_pstmt(value)]
  end
end

.quote_value(value, column = nil) ⇒ Object

:nodoc:



543
544
545
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 543

def quote_value(value, column = nil) #:nodoc:
  connection.quote_value_for_pstmt(value,column)
end

.replace_bind_variables(statement, values) ⇒ Object

Check delete_all method, which passes a ? and array of params, as an example. This method replace_bind_variables replaces those ? with a string of the values. For Eg:- if said Wood.delete(), delete all sends the condition as [“id in (?)”, [1,2,3,4]] This method sends the condition part back as string, “id in (1,2,3,4)” originally Now this method is modified to send out a hash containing the parameter array and the sql to be prepared



777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 777

def replace_bind_variables(statement, values)
  raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size)
  bound = values.dup
  return_hash = {}
  return_hash["paramArray"] = []
  return_hash["sqlSegment"] = ''

  return_hash["sqlSegment"] = 
     statement.gsub('?') {
        str_seg = ''
        param_array = quote_bound_value(bound.shift)
        if param_array && param_array.size > 1
          for index in 0...param_array.size-1
            str_seg << '?,'
          end
        end
        str_seg << '?'
        return_hash["paramArray"] = return_hash["paramArray"] + param_array unless param_array.nil?
        str_seg
      }
  return_hash
end

.replace_named_bind_variables(statement, bind_vars) ⇒ Object

Replaces the named parameters with ‘?’ and pass a hash containing the sql’s condition clause segment and the parameters array



801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 801

def replace_named_bind_variables(statement, bind_vars) #:nodoc:
  return_hash = {}
  return_hash["paramArray"] = []
  return_hash["sqlSegment"] = ''

  return_hash["sqlSegment"] =
    statement.gsub(/(:?):([a-zA-Z]\w*)/) {

      if $1 == ':' # skip postgresql casts
        $& # return the whole match
      elsif bind_vars.include?(match = $2.to_sym)
        str_seg = ''
        param_array = quote_bound_value(bind_vars[match])
        if param_array.size > 1
          for index in 0...param_array.size-1
            str_seg << '?,'
          end
        end
        str_seg << '?'
        return_hash["paramArray"] = return_hash["paramArray"] + param_array
        str_seg
      else
        raise PreparedStatementInvalid, "missing value for :#{match} in #{statement}"
      end
    }
  return_hash
end

.sanitize_sql_array(ary) ⇒ Object

Accepts an array of conditions. The array has each value sanitized and interpolated into the SQL statement.



722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 722

def sanitize_sql_array(ary)
  statement, *values = ary
  return_hash = {}

  if values.first.is_a?(Hash) and statement =~ /:\w+/
    replace_named_bind_variables(statement, values.first)
  elsif statement && statement.include?('?')
    replace_bind_variables(statement, values)
  else
    if !values.nil? && values.size > 0
      return_hash["sqlSegment"] = statement % values.collect { |value| connection.quote_string(value.to_s) }
    else
      return_hash["sqlSegment"] = statement
    end
    return_hash["paramArray"] = []
    return_hash
  end
end

.sanitize_sql_for_assignment(assignments) ⇒ Object

Accepts an array, hash, or string of SQL conditions and sanitizes them into a valid SQL fragment for a SET clause.

{ :name => nil, :group_id => 4 }  returns "name = NULL , group_id='4'"


691
692
693
694
695
696
697
698
699
700
701
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 691

def sanitize_sql_for_assignment(assignments)
  return_hash = {}
  case assignments
    when Array; sanitize_sql_array(assignments)
    when Hash;  sanitize_sql_hash_for_assignment(assignments)
    else        
      return_hash["sqlSegment"] = assignments
      return_hash["paramArray"] = nil
      return_hash
  end
end

.sanitize_sql_for_conditions(condition, table_name = quoted_table_name) ⇒ Object Also known as: sanitize_sql, sanitize_conditions



703
704
705
706
707
708
709
710
711
712
713
714
715
716
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 703

def sanitize_sql_for_conditions(condition, table_name = quoted_table_name)
  return nil if condition.blank?

  return_hash = {}

  case condition
    when Array; sanitize_sql_array(condition)
    when Hash;  sanitize_sql_hash_for_conditions(condition, table_name)
    else
      return_hash["sqlSegment"] = condition
      return_hash["paramArray"] = nil
      return_hash
  end
end

.sanitize_sql_hash_for_assignment(attrs) ⇒ Object

Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.

{ :status => nil, :group_id => 1 }
  # => "status = NULL , group_id = 1"


677
678
679
680
681
682
683
684
685
686
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 677

def sanitize_sql_hash_for_assignment(attrs)
  return_hash = {}
  return_hash["paramArray"] = []

  return_hash["sqlSegment"] = attrs.map do |attr, value|
    return_hash["paramArray"] += quote_bound_value(value)
    "#{connection.quote_column_name(attr)} = ?"
  end.join(', ')
  return_hash
end

.sanitize_sql_hash_for_conditions(attrs, table_name = quoted_table_name) ⇒ Object Also known as: sanitize_sql_hash



741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 741

def sanitize_sql_hash_for_conditions(attrs, table_name = quoted_table_name)
  attrs = expand_hash_conditions_for_aggregates(attrs)
  temp_table_name = table_name

  param_array = []

  conditions = attrs.map do |attr, value|
    unless value.is_a?(Hash)
      attr = attr.to_s

      # Extract table name from qualified attribute names.
      if attr.include?('.')
        table_name, attr = attr.split('.', 2)
        table_name = connection.quote_table_name(table_name)
      else
        table_name = temp_table_name
      end

      param_array << value unless value.nil?
      attribute_condition("#{table_name}.#{connection.quote_column_name(attr)}", value)
    else
      sql_param_hash = sanitize_sql_hash_for_conditions(value, connection.quote_table_name(attr.to_s))
      param_array = param_array + sql_param_hash["paramArray"] unless sql_param_hash["paramArray"].empty?
      sql_param_hash["sqlSegment"]
    end
  end.join(' AND ')

  replace_bind_variables(conditions, expand_range_bind_variables(param_array))
end

.type_condition(table_alias = nil) ⇒ Object



646
647
648
649
650
651
652
653
654
655
656
657
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 646

def type_condition(table_alias=nil)
  param_array = []
  quoted_table_alias = self.connection.quote_table_name(table_alias || table_name)
  quoted_inheritance_column = connection.quote_column_name(inheritance_column)
  param_array << self.connection.quote_value_for_pstmt(sti_name)
  type_condition = subclasses.inject("#{quoted_table_alias}.#{quoted_inheritance_column} = ? ") do |condition, subclass|
    param_array << self.connection.quote_value_for_pstmt(subclass.sti_name)
    condition << "OR #{quoted_table_alias}.#{quoted_inheritance_column} = ? "
  end

  [" (#{type_condition}) "] + param_array
end

.update_all(updates, conditions = nil, options = {}) ⇒ Object



547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 547

def update_all(updates, conditions = nil, options = {})
  sql_values_hash = sanitize_sql_for_assignment(updates)
  param_array = sql_values_hash["paramArray"]

  sql  = "UPDATE #{quoted_table_name} SET #{sql_values_hash["sqlSegment"]} "

  scope = scope(:find)

  select_sql = ""
  temp_param_array = add_conditions!(select_sql, conditions, scope)

  if !param_array.nil? && !param_array.empty?
    param_array += temp_param_array
  else
    param_array = temp_param_array
  end

  if options.has_key?(:limit) || (scope && scope[:limit])
    # Only take order from scope if limit is also provided by scope, this
    # is useful for updating a has_many association with a limit.
    add_order!(select_sql, options[:order], scope)

    temp_options = options.dup # Ensure that the necessary parameters are received in the duplicate, so that the original hash is intact
    temp_options[:paramArray] = [] # To receive the values for limit and offset.
    add_limit!(select_sql, temp_options, scope)
    param_array = param_array + temp_options[:paramArray]

    sql.concat(connection.limited_update_conditions(select_sql, quoted_table_name, connection.quote_column_name(primary_key)))
  else
    add_order!(select_sql, options[:order], nil)
    sql.concat(select_sql)
  end

  pstmt = connection.prepare(sql, "#{name} Update")
  connection.prepared_update(pstmt, param_array)
end

.update_counters_without_lock(id, counters) ⇒ Object



584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 584

def update_counters_without_lock(id, counters)
  updates = counters.inject([]) { |list, (counter_name, increment)|
    sign = increment < 0 ? "-" : "+"
    list << "#{connection.quote_column_name(counter_name)} = COALESCE(#{connection.quote_column_name(counter_name)}, 0) #{sign} #{increment.abs}"
  }.join(", ")

  if id.is_a?(Array)
    ids_list = id.map {|i|
      connection.quote_value_for_pstmt(i)
    }
    condition = ["#{connection.quote_column_name(primary_key)} IN  (?)", ids_list]
  else
    param_value = connection.quote_value_for_pstmt(id)
    condition = ["#{connection.quote_column_name(primary_key)} = ?", param_value]
  end

  update_all(updates, condition)
end

.validates_uniqueness_of(*attr_names) ⇒ Object



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 192

def validates_uniqueness_of(*attr_names)
  configuration = { :case_sensitive => true }
  configuration.update(attr_names.extract_options!)

  validates_each(attr_names,configuration) do |record, attr_name, value|
    # The check for an existing value should be run from a class that
    # isn't abstract. This means working down from the current class
    # (self), to the first non-abstract class. Since classes don't know
    # their subclasses, we have to build the hierarchy between self and
    # the record's class.
    class_hierarchy = [record.class]
    while class_hierarchy.first != self
      class_hierarchy.insert(0, class_hierarchy.first.superclass)
    end

    # Now we can work our way down the tree to the first non-abstract
    # class (which has a database table to query from).
              finder_class = class_hierarchy.detect { |klass| !klass.abstract_class? }

    column = finder_class.columns_hash[attr_name.to_s]

    if value.nil?
      comparison_operator = "IS NULL"
    elsif column.text?
      comparison_operator = "#{connection.case_sensitive_equality_operator} ?"
      value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s
    else
      comparison_operator = "= ?"
    end

    sql_attribute = "#{record.class.quoted_table_name}.#{connection.quote_column_name(attr_name)}"

    if value.nil? || (configuration[:case_sensitive] || !column.text?)
      condition_sql = "#{sql_attribute} #{comparison_operator}"
      condition_params = [value] if(!value.nil?) #Add the value only if not nil, because in case of nil comparison op is IS NULL
    else
      condition_sql = "LOWER(#{sql_attribute}) #{comparison_operator}"
      condition_params = [value.mb_chars.downcase]
    end

    if scope = configuration[:scope]
      Array(scope).map do |scope_item|
        scope_value = record.send(scope_item)
        condition_sql << " AND " << attribute_condition("#{record.class.quoted_table_name}.#{scope_item}", scope_value)
        condition_params << scope_value
      end
    end

    unless record.new_record?
      condition_sql << " AND #{record.class.quoted_table_name}.#{record.class.primary_key} <> ?"
      condition_params << record.send(:id)
    end

    finder_class.with_exclusive_scope do
      if finder_class.exists?([condition_sql, *condition_params])
        record.errors.add(attr_name, :taken, :default => configuration[:message], :value => value)
      end
    end
  end
end

.with_scope(method_scoping = {}, action = :merge, &block) ⇒ Object



469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 469

def with_scope(method_scoping = {}, action = :merge, &block)
  method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping)

  # Dup first and second level of hash (method and params).
  method_scoping = method_scoping.inject({}) do |hash, (method, params)|
    hash[method] = (params == true) ? params : params.dup
    hash
  end

  method_scoping.assert_valid_keys([ :find, :create ])

  if f = method_scoping[:find]
    f.assert_valid_keys(VALID_FIND_OPTIONS)
    set_readonly_option! f
  end

  # Merge scopings
  if [:merge, :reverse_merge].include?(action) && current_scoped_methods
    method_scoping = current_scoped_methods.inject(method_scoping) do |hash, (method, params)|
      case hash[method]
        when Hash
          if method == :find
            (hash[method].keys + params.keys).uniq.each do |key|
              merge = hash[method][key] && params[key] # merge if both scopes have the same key
              if key == :conditions && merge
                if params[key].is_a?(Hash) && hash[method][key].is_a?(Hash)
                  sql_param_hash    = merge_conditions(hash[method][key].deep_merge(params[key]))
                  hash[method][key] = [sql_param_hash["sqlSegment"]] + sql_param_hash["paramArray"]
                else
                  sql_param_hash    = merge_conditions(params[key], hash[method][key])
                  hash[method][key] = [sql_param_hash["sqlSegment"]] + sql_param_hash["paramArray"]
                end
              elsif key == :include && merge
                hash[method][key] = merge_includes(hash[method][key], params[key]).uniq
              elsif key == :joins && merge
                hash[method][key] = merge_joins(params[key], hash[method][key])
              else
                hash[method][key] = hash[method][key] || params[key]
              end
            end
          else
            if action == :reverse_merge
              hash[method] = hash[method].merge(params)
            else
              hash[method] = params.merge(hash[method])
            end
          end
        else
          hash[method] = params
      end
      hash
    end
  end

  self.scoped_methods << method_scoping
  begin
    yield
  ensure
    self.scoped_methods.pop
  end
end

Instance Method Details

#destroy_without_lockObject

Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can’t be persisted).



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 36

def destroy_without_lock
  unless new_record?
    # Prepare the sql for deleting a row
    pstmt = connection.prepare(
              "DELETE FROM #{self.class.quoted_table_name} " +
              "WHERE #{connection.quote_column_name(self.class.primary_key)} = ?",
              "#{self.class.name} Destroy"
            )
    # Execute the prepared Statement
    connection.prepared_delete(pstmt, [connection.quote_value_for_pstmt(quoted_id)])
  end

  @destroyed = true
  freeze
end

#quote_value(value, column = nil) ⇒ Object

:nodoc:



30
31
32
# File 'lib/active_record/connection_adapters/ibm_db_pstmt.rb', line 30

def quote_value(value, column = nil) #:nodoc:
  connection.quote_value_for_pstmt(value,column)
end