| 
      
      
      From: Michael N. <mne...@us...> - 2002-09-05 09:57:17
      
     | 
| Update of /cvsroot/ruby-dbi/subprojects/ruby-db2/samples
In directory usw-pr-cvs1:/tmp/cvs-serv2947/ruby-db2/samples
Added Files:
	db2.rb sqlsh.rb test.rb test2.rb 
Log Message:
initial import from local CVS repository
--- NEW FILE: db2.rb ---
require "db2/db2cli.rb"
module DB2
  FINALIZE_INFO = {}
  FINALIZE_PROC = proc do |id|
    info =  FINALIZE_INFO[id]
    if $DEBUG then
      $stderr.puts "freeing handle <#{info[1]}> (#{info[0]})"
    end
    DB2CLI::SQLFreeHandle(info[0], info[1]) 
  end 
  class CLIError < Exception
    attr_reader :sql_state, :native_error, :message_text
    def initialize(sql_state, native_error, message_text)
      @sql_state    = sql_state
      @native_error = native_error
      @message_text = message_text
    end
    
    def message
      @message_text
    end    
  end
  class Handle
    include DB2CLI
    def initialize(handle_type, parent_handle)
      @handle_type = handle_type
      @handle = parent_handle
      rc, handle = SQLAllocHandle(@handle_type, @handle)
      check_rc(rc)
      @handle = handle
      add_finalizer
     end
    def free
      rc = SQLFreeHandle(@handle_type, @handle)
      check_rc(rc)
    end
    def handle
      @handle
    end
    private
    def add_finalizer
      DB2::FINALIZE_INFO[self.id] = [@handle_type.dup, @handle.dup]  
      ObjectSpace.define_finalizer(self, DB2::FINALIZE_PROC)
    end
    def check_rc(rc)
      if rc != SQL_SUCCESS and rc != SQL_SUCCESS_WITH_INFO then 
        err = SQLGetDiagRec(@handle_type, @handle, 1, 1024)
        raise CLIError.new(err[1], err[2], err[3]) 
      end
    end
  end # class Handle
  class Environment < Handle
    def initialize
      super(SQL_HANDLE_ENV, SQL_NULL_HANDLE)
    end
    def dataSources
      data_sources_buffer
    end
    def createConnection(*a)
      Connection.new(self, *a)
    end
    private
    def data_sources_buffer(buffer_length = 1024)
      retval = []
      max_buffer_length = buffer_length
      a = SQLDataSources(@handle, SQL_FETCH_FIRST, SQL_MAX_DSN_LENGTH+1, buffer_length)
      retval << [a[1], a[3]]
      max_buffer_length = [max_buffer_length, a[4]].max
      loop do
        a = SQLDataSources(@handle, SQL_FETCH_NEXT, SQL_MAX_DSN_LENGTH+1, buffer_length)
        break if a[0] == SQL_NO_DATA_FOUND
        retval << [a[1], a[3]]
        max_buffer_length = [max_buffer_length, a[4]].max
      end 
     
      if max_buffer_length > buffer_length then
        data_sources_buffer(max_buffer_length)
      else
        retval
      end
    end
  end # class Environment
  class Connection < Handle
    def initialize(environment, *conn_params)
      @env = environment
      super(SQL_HANDLE_DBC, @env.handle)
      @connected = false
      unless conn_params.empty?
        connect(*conn_params)
      end
    end
    def connect(server_name, user_name="", auth="")
      rc = SQLConnect(@handle, server_name, user_name, auth) 
      check_rc(rc)
      @connected = true
    end
    def disconnect
      rc = SQLDisconnect(@handle)
      check_rc(rc)
      @connected = false
    end
    def rollback
      rc = SQLEndTran(@handle_type, @handle, SQL_ROLLBACK)
      check_rc(rc)
    end
    def commit
      rc = SQLEndTran(@handle_type, @handle, SQL_COMMIT)
      check_rc(rc)
    end
    def createStatement
      Statement.new(self)
    end
  end # class Connection
  class Statement < Handle
    def initialize(connection)
      @conn = connection
      super(SQL_HANDLE_STMT, @conn.handle)
    end
    def prepare(sql)
      rc = SQLPrepare(@handle, sql)
      check_rc(rc)
      self
    end
    def freeStmt(options)
      rc = SQLFreeStmt(@handle, options) 
      ckeck_rc(rc)
    end
    def execute
      rc = SQLExecute(@handle)
      check_rc(rc)
      self
    end
    def execDirect(sql)
      rc = SQLExecDirect(@handle, sql)
      check_rc(rc)
      self
    end
    def tables(schema_name="%", table_name="%", table_type="TABLE") 
      rc = SQLTables(@handle, "", schema_name, table_name, table_type)
      check_rc(rc)
      self 
    end
    def rowCount
      rc, rowcount = SQLRowCount(@handle)
      check_rc(rc)
      rowcount
    end
    def numResultCols
      rc, cols = SQLNumResultCols(@handle)
      check_rc(rc)
      cols
    end
    def colNames
      rc, nr_cols = SQLNumResultCols(@handle)
    
      (1..nr_cols).collect do |c| 
        rc, name, bl, type, col_sz = SQLDescribeCol(@handle, c, 1024)
        name
      end 
    end
    def fetchAll
      if block_given?
        while (row=fetchRow) do
          yield row
        end
      else
        res = []
        while (row=fetchRow) do
          res << row
        end
        res
      end
    end
    def fetchRow(orientation=SQL_FETCH_NEXT, offset=0)
      rc, nr_cols = SQLNumResultCols(@handle)
    
      cols = (1..nr_cols).collect do |c| 
        rc, name, bl, type, col_sz = SQLDescribeCol(@handle, c, 1024)
        [name, type, col_sz]
      end 
      rc = SQLFetchScroll(@handle, orientation, offset)
      return nil if rc == SQL_NO_DATA_FOUND
      raise "ERROR" unless rc == SQL_SUCCESS 
    
      retval = [] 
      cols.each_with_index do |c, i|
        rc, content = SQLGetData(@handle, i+1, c[1], c[2]) 
        retval << content
      end 
      return retval
    end
    alias :fetch :fetchRow
  end # class Statement
end # module DB2
--- NEW FILE: sqlsh.rb ---
require "readline"
require "db2"
class ReadlineControl
  
  def initialize
    @keywords = []
    set_prompt
    Readline.completion_proc = proc {|str| complete(str) }
  end
  def add_keywords(arr)
    @keywords += arr
  end
  def complete(str)
    @keywords.grep(/^#{Regexp.escape(str)}/i)
  end
  def set_prompt(prompt="> ")
    @prompt = prompt
  end
  def readline
    Readline.readline(@prompt, true)
  end
end
if ARGV.size < 1 or ARGV.size > 3
  puts
  puts "USAGE: #{$0} database [, user [, password] ]"
  puts
  exit 1
else
  DB   = ARGV.shift
  USER = ARGV.shift || ""
  PASS = ARGV.shift || ""
end
puts
begin
  print "  CONNECT TO #{DB}" 
  print " USER '#{USER}'" unless USER.empty?
  print " PASSWORD '#{PASS}'" unless PASS.empty?
  puts
  Env  = DB2::Environment.new
  Conn = Env.createConnection("SAMPLE")
rescue DB2::CLIError => err
    puts
    puts err.message
    puts
end
puts
PROMPT      = "db2 => "
PROMPT_CONT = "db2 =| "
SQL_KEYWORDS = %w(
  INSERT DELETE UPDATE SELECT FROM WHERE IN LIKE SET VALUES INTO
  CREATE TABLE DROP 
  COMMIT ROLLBACK
  CHAR VARCHAR INT INTEGER NUMBER FLOAT REAL LONG CLOB BLOB DECIMAL DBCLOB DBBLOB
)
rd = ReadlineControl.new
rd.add_keywords SQL_KEYWORDS
rd.set_prompt(PROMPT)
def output_table(rows)
  collength = [] 
 
  rows.each {|r| r.each_with_index {|c,i|  
    r[i] = c.to_s.chomp("\000")
    c = r[i]
    collength[i] = c.size if collength[i].nil? or c.size > collength[i] 
  } }
  split_line = " +"
  collength.each {|col|
    split_line << "-" * (col+2) + "+"
  }
  
  puts
  puts split_line
  # output table
  rows.each_with_index {|r, rn|
    print " |"
    r.each_with_index {|c,i|
      print sprintf(" %*2$s |", c.to_s, -(collength[i]))
    }
    puts
    puts split_line if rn == 0
  }
  puts split_line
  puts
end
loop {
  line = rd.readline
  line.chomp!
  next if line.empty?
 
  begin
    if line =~ /^\\/ then
      if line =~ /^\\list tables/i then
        stmt = Conn.createStatement.tables
      elsif line =~ /^\\list views/i then
        stmt = Conn.createStatement.tables("%", "%", "VIEW")
      elsif line =~ /^\\quit/i then
        break 
      else
        puts
        puts "Unknown command!"
        puts
        next
      end
    else
      # multi-line
      if line[-1].chr == "\\" then
        line.chop!
        rd.set_prompt(PROMPT_CONT)
        loop {
          ln = rd.readline
          line.chomp!
          next if line.empty?
           
          if ln[-1].chr == "\\" then
            line += ln.chop
          else
            line += ln
            break
          end
        }
      end
      rd.set_prompt(PROMPT)
      stmt = Conn.createStatement.execDirect(line)
    end
    head = stmt.colNames 
    next if head.empty? 
    rows = stmt.fetchAll 
    rows[0,0] = [head]
    output_table(rows)
  rescue DB2::CLIError => err
    puts
    puts err.message
    puts
  end
}
Conn.disconnect
Conn.free
Env.free
--- NEW FILE: test.rb ---
require "db2/db2cli.rb"
include DB2CLI
rc, env  = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE); p rc
puts "Datasources: "
p SQLDataSources(env, SQL_FETCH_FIRST, SQL_MAX_DSN_LENGTH+1, 200) 
loop { 
  a = SQLDataSources(env, SQL_FETCH_NEXT, SQL_MAX_DSN_LENGTH+1, 200)
  break if a[0] == SQL_NO_DATA_FOUND
  p a
}
puts "--------------------"
readline
rc, dbc  = SQLAllocHandle(SQL_HANDLE_DBC, env); p rc
p SQLConnect(dbc, "SAMPLE", "", "")
rc, stmt = SQLAllocHandle(SQL_HANDLE_STMT, dbc); p rc
p SQLPrepare(stmt, "SELECT * FROM EMPLOYEE")
p SQLExecute(stmt)
DELIM = "  "
rc, COLS = SQLNumResultCols(stmt)
cols = (1..COLS).collect {|c| 
  rc, name, bl, type, col_sz = SQLDescribeCol(stmt, c, 100)
  [name, type, col_sz]
}
cols.each {|c| print c[0], DELIM }
puts
while SQLFetch(stmt) == SQL_SUCCESS do
  cols.each_with_index {|c, i|
    rc, content = SQLGetData(stmt, i+1, c[1], 100) 
    print content, DELIM 
  }
  puts 
end
p SQLFreeStmt(stmt, SQL_CLOSE)
################
def get_row_as_hash(stmt)
  rc, nr_cols = SQLNumResultCols(stmt)
  
  cols = (1..nr_cols).collect do |c| 
    rc, name, bl, type, col_sz = SQLDescribeCol(stmt, c, 100)
    [name, type, col_sz]
  end 
  rc = SQLFetch(stmt)
  return nil if rc == SQL_NO_DATA_FOUND
  raise "ERROR" unless rc == SQL_SUCCESS 
  
  retval = {}
  cols.each_with_index do |c, i|
    rc, content = SQLGetData(stmt, i+1, c[1], c[2]) 
    retval[c[0]] = content
  end 
  return retval
end
################
puts "HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH"
p SQLTables(stmt, "", "", "%", "")
while (c=get_row_as_hash(stmt))
  p c
end
puts "HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH"
p SQLFreeStmt(stmt, SQL_CLOSE)
p SQLExecDirect(stmt, "SELECT 2, 2.3+3.4, 'Hallo' FROM EMPLOYEE")
#p SQLExecDirect(stmt, "SELECT YEARS FROM STAFF WHERE YEARS IS NULL")
p "*************************************"
p SQLColAttribute(stmt, 2, SQL_DESC_TYPE_NAME, 200)
p SQLColAttribute(stmt, 2, SQL_DESC_TYPE, nil)
p "*************************************"
p SQLFetch(stmt)
puts "=================================="
p SQLGetData(stmt, 1, SQL_INTEGER)
p SQLGetData(stmt, 1, SQL_SMALLINT)
p SQLGetData(stmt, 2, SQL_DOUBLE)
#p SQLGetData(stmt, 2, SQL_FLOAT)
#p SQLGetData(stmt, 2, SQL_REAL)
p SQLGetData(stmt, 3, SQL_INTEGER, 20000)
puts "=================================="
p SQLFreeStmt(stmt, SQL_CLOSE)
puts "-----111111111111111-----------"
p SQLExecDirect(stmt, "INSERT INTO meintable (test,hallo) VALUES (2,3)")
p SQLGetDiagRec(SQL_HANDLE_STMT, stmt, 1, 1000)
p SQLRowCount(stmt)
p SQLEndTran(SQL_HANDLE_DBC, dbc, SQL_ROLLBACK)
p SQLFreeHandle(SQL_HANDLE_STMT, stmt)
p SQLDisconnect(dbc)
p SQLFreeHandle(SQL_HANDLE_DBC, dbc)
p SQLFreeHandle(SQL_HANDLE_ENV, env)
--- NEW FILE: test2.rb ---
require "db2.rb"
include DB2
env = Environment.new
conn = env.createConnection("SAMPLE")
stmt = conn.createStatement
stmt.prepare("SELECT * FROM EMPLOYEE").execute
p stmt.fetchAll
conn.disconnect
 |