Namespace

Files

Class/Module Index [+]

Quicksearch

ArJdbc::DB2

Constants

ADD_LOB_CALLBACK

TODO kind of standard AR configuration option for this would be nice :

DRIVER_NAME
HAVE_LIMIT

only record precision and scale for types that can set them via CREATE TABLE: publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000927.html

HAVE_PRECISION
HAVE_SCALE
NATIVE_DATABASE_TYPES

Public Class Methods

arel2_visitors(config) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 55
def self.arel2_visitors(config)
  require 'arel/visitors/db2'
  { 'db2'   => ::Arel::Visitors::DB2, 'as400' => ::Arel::Visitors::DB2 }
end
column_selector() click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 47
def self.column_selector
  [ /(db2|as400|zos)/, lambda { |cfg, column| column.extend(::ArJdbc::DB2::Column) } ]
end
extended(base) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 22
def self.extended(base)
  if ADD_LOB_CALLBACK && ! lob_callback_added?
    ActiveRecord::Base.class_eval do
      def after_save_with_db2_lob
        lob_columns = self.class.columns.select { |c| c.sql_type =~ /blob|clob/ }
        lob_columns.each do |column|
          value = ::ArJdbc::SerializedAttributesHelper.dump_column_value(self, column)
          next if value.nil? # already set NULL

          connection.write_large_object(
            column.type == :binary, column.name, 
            self.class.table_name, 
            self.class.primary_key, 
            quote_value(id), value
          )
        end
      end
      alias after_save_with_db2zos_blob after_save_with_db2_lob # <-compat
    end
    # TODO this should be changed to :after_save_with_db2_lob :
    ActiveRecord::Base.after_save :after_save_with_db2zos_blob # <-compat
    lob_callback_added!
  end
end
jdbc_connection_class() click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 51
def self.jdbc_connection_class
  ::ActiveRecord::ConnectionAdapters::DB2JdbcConnection
end
lob_callback_added!() click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 14
def self.lob_callback_added! # :nodoc
  @@_lob_callback_added = true
end
lob_callback_added?() click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 10
def self.lob_callback_added? # :nodoc
  @@_lob_callback_added
end

Public Instance Methods

_execute(sql, name = nil) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 219
def _execute(sql, name = nil)
  if self.class.select?(sql)
    @connection.execute_query(sql)
  elsif self.class.insert?(sql)
    (@connection.execute_insert(sql) or last_insert_id(sql)).to_i
  else
    @connection.execute_update(sql)
  end
end
adapter_name() click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 60
def adapter_name
  'DB2'
end
add_index(table_name, column_name, options = {}) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 429
def add_index(table_name, column_name, options = {})
  if ! zos? || ( table_name.to_s == ActiveRecord::Migrator.schema_migrations_table_name.to_s )
    column_name = column_name.to_s if column_name.is_a?(Symbol)
    super
  else
    statement = 'CREATE'
    statement << ' UNIQUE ' if options[:unique]
    statement << " INDEX #{ActiveRecord::Base.table_name_prefix}#{options[:name]} "
    statement << " ON #{table_name}(#{column_name})"
    
    execute statement
  end
end
add_limit_offset!(sql, options) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 368
def add_limit_offset!(sql, options)
  replace_limit_offset!(sql, options[:limit], options[:offset])
end
add_quotes(name) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 552
def add_quotes(name)
  return name unless name
  %{"#{name}"}
end
after_save_with_db2_lob() click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 25
def after_save_with_db2_lob
  lob_columns = self.class.columns.select { |c| c.sql_type =~ /blob|clob/ }
  lob_columns.each do |column|
    value = ::ArJdbc::SerializedAttributesHelper.dump_column_value(self, column)
    next if value.nil? # already set NULL

    connection.write_large_object(
      column.type == :binary, column.name, 
      self.class.table_name, 
      self.class.primary_key, 
      quote_value(id), value
    )
  end
end
as400?() click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 647
def as400?
  return @as400 unless @as400.nil?
  @as400 = 
    if url = @config[:url]
      !!( url =~ /^jdbc:as400:/ )
    else
      nil
    end
end
change_column(table_name, column_name, type, options = {}) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 478
def change_column(table_name, column_name, type, options = {})
  data_type = type_to_sql(type, options[:limit], options[:precision], options[:scale])
  sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DATA TYPE #{data_type}"
  as400? ? execute_and_auto_confirm(sql) : execute(sql)
  reorg_table(table_name)

  if options.include?(:default) and options.include?(:null)
    # which to run first?
    if options[:null] or options[:default].nil?
      change_column_null(table_name, column_name, options[:null])
      change_column_default(table_name, column_name, options[:default])
    else
      change_column_default(table_name, column_name, options[:default])
      change_column_null(table_name, column_name, options[:null])
    end
  elsif options.include?(:default)
    change_column_default(table_name, column_name, options[:default])
  elsif options.include?(:null)
    change_column_null(table_name, column_name, options[:null])
  end
end
change_column_default(table_name, column_name, default) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 468
def change_column_default(table_name, column_name, default)
  if default.nil?
    sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} DROP DEFAULT"
  else
    sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET WITH DEFAULT #{quote(default)}"
  end
  as400? ? execute_and_auto_confirm(sql) : execute(sql)
  reorg_table(table_name)
end
change_column_null(table_name, column_name, null) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 458
def change_column_null(table_name, column_name, null)
  if null
    sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} DROP NOT NULL"
  else
    sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET NOT NULL"
  end
  as400? ? execute_and_auto_confirm(sql) : execute(sql)
  reorg_table(table_name)
end
columns(table_name, name = nil) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 525
def columns(table_name, name = nil)
  columns = @connection.columns(table_name.to_s, name, db2_schema)

  if zos?
    # Remove the mighty db2_generated_rowid_for_lobs from the list of columns
    columns = columns.reject { |col| "db2_generated_rowid_for_lobs" == col.name }
  end
  # scrub out sizing info when CREATE TABLE doesn't support it
  # but JDBC reports it (doh!)
  for column in columns
    base_sql_type = column.sql_type.sub(/\(.*/, "").upcase
    column.limit = nil unless HAVE_LIMIT.include?(base_sql_type)
    column.precision = nil unless HAVE_PRECISION.include?(base_sql_type)
    #column.scale = nil unless HAVE_SCALE.include?(base_sql_type)
  end

  columns
end
execute_and_auto_confirm(sql) click to toggle source

holy moly batman! all this to tell AS400 "yes i am sure"

# File lib/arjdbc/db2/adapter.rb, line 198
def execute_and_auto_confirm(sql)
  begin
    @connection.execute_update "call qsys.qcmdexc('QSYS/CHGJOB INQMSGRPY(*SYSRPYL)',0000000031.00000)"
    @connection.execute_update "call qsys.qcmdexc('ADDRPYLE SEQNBR(9876) MSGID(CPA32B2) RPY(''I'')',0000000045.00000)"
  rescue Exception => e
    raise "Could not call CHGJOB INQMSGRPY(*SYSRPYL) and ADDRPYLE SEQNBR(9876) MSGID(CPA32B2) RPY('I').\n" +
          "Do you have authority to do this?\n\n" + e.to_s
  end

  result = execute sql

  begin
    @connection.execute_update "call qsys.qcmdexc('QSYS/CHGJOB INQMSGRPY(*DFT)',0000000027.00000)"
    @connection.execute_update "call qsys.qcmdexc('RMVRPYLE SEQNBR(9876)',0000000021.00000)"
  rescue Exception => e
    raise "Could not call CHGJOB INQMSGRPY(*DFT) and RMVRPYLE SEQNBR(9876).\n" +
          "Do you have authority to do this?\n\n" + e.to_s
  end
  result
end
expand_double_quotes(name) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 563
def expand_double_quotes(name)
  return name unless name && name['"']
  name.gsub(/"/,'""')
end
explain(query, *binds) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 18
def explain(query, *binds)
  # TODO: Explain this! Do not remove !
end
indexes(table_name, name = nil) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 548
def indexes(table_name, name = nil)
  @connection.indexes(table_name, name, db2_schema)
end
jdbc_columns(table_name, name = nil) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 544
def jdbc_columns(table_name, name = nil)
  columns(table_name, name)
end
last_insert_id(sql) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 229
def last_insert_id(sql)
  table_name = sql.split(/\s/)[2]
  result = select(ActiveRecord::Base.send(:sanitize_sql, %[SELECT IDENTITY_VAL_LOCAL() AS last_insert_id FROM #{table_name}], nil))
  result.last['last_insert_id']
end
modify_types(types) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 354
def modify_types(types)
  super(types)
  types[:primary_key] = 'int not null generated by default as identity (start with 1) primary key'
  types[:string][:limit] = 255
  types[:integer][:limit] = nil
  types[:boolean] = {:name => "decimal(1)"}
  types
end
native_database_types() click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 82
def native_database_types
  super.merge(NATIVE_DATABASE_TYPES)
end
next_sequence_value(sequence_name) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 193
def next_sequence_value(sequence_name)
  select_value("SELECT NEXT VALUE FOR #{sequence_name} FROM sysibm.sysdummy1")
end
pk_and_sequence_for(table) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 292
def pk_and_sequence_for(table)
  # In JDBC/DB2 side, only upcase names of table and column are handled.
  keys = super(table.upcase)
  if keys && keys[0]
    # In ActiveRecord side, only downcase names of table and column are handled.
    keys[0] = keys[0].downcase
  end
  keys
end
prefetch_primary_key?(table_name = nil) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 177
def prefetch_primary_key?(table_name = nil)
  # TRUE if the table has no identity column
  names = table_name.upcase.split(".")
  sql = ""
  if as400?
    sql = "SELECT 1 FROM SYSIBM.SQLPRIMARYKEYS WHERE "
    sql += "TABLE_SCHEM = '#{names.first}' AND " if names.size == 2
    sql += "TABLE_NAME = '#{names.last}'"
  else
    sql = "SELECT 1 FROM SYSCAT.COLUMNS WHERE IDENTITY = 'Y' "
    sql += "AND TABSCHEMA = '#{names.first}' " if names.size == 2
    sql += "AND TABNAME = '#{names.last}'"
  end
  select_one(sql).nil?
end
quote_column_name(column_name) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 350
def quote_column_name(column_name)
  column_name.to_s
end
recreate_database(name, options = {}) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 425
def recreate_database(name, options = {})
  tables.each { |table| drop_table("#{db2_schema}.#{table}") }
end
remove_index(table_name, options = { }) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 443
def remove_index(table_name, options = { })
  execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
end
replace_limit_offset!(sql, limit, offset) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 396
def replace_limit_offset!(sql, limit, offset)
  if limit
    limit = limit.to_i
    if !offset
      if limit == 1
        sql << " FETCH FIRST ROW ONLY"
      else
        sql << " FETCH FIRST #{limit} ROWS ONLY"
      end
    else
      offset = offset.to_i
      sql.sub!(/SELECT/, 'SELECT B.* FROM (SELECT A.*, row_number() over () AS internal$rownum FROM (SELECT')
      sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset}"
    end
  end
  sql
end
runstats_for_table(tablename, priority=10) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 421
def runstats_for_table(tablename, priority=10)
  @connection.execute_update "call sysproc.admin_cmd('RUNSTATS ON TABLE #{tablename} WITH DISTRIBUTION AND DETAILED INDEXES ALL UTIL_IMPACT_PRIORITY #{priority}')"
end
strip_quotes(str) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 557
def strip_quotes(str)
  return str unless str
  return str unless /^(["']).*\11$$/ =~ str
  str[1..-2]
end
tables() click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 515
def tables
  @connection.tables(nil, db2_schema, nil, ["TABLE"])
end
type_to_sql(type, limit = nil, precision = nil, scale = nil) click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 363
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
  limit = nil if type.to_sym == :integer
  super(type, limit, precision, scale)
end
zos?() click to toggle source
# File lib/arjdbc/db2/adapter.rb, line 637
def zos?
  return @zos unless @zos.nil?
  @zos = 
    if url = @config[:url]
      !!( url =~ /^jdbc:db2j:net:/ && @config[:driver] == DRIVER_NAME )
    else
      nil
    end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.