#!/usr/local/bin/ruby

#$Id: ora_rdbc1.rb,v 1.4 1999/11/10 09:09:08 nakamura Exp nakamura $

=begin

module ORA_RDBC1

=end
require "oracle"
require "rdbc1.rb"

class ORAcursor
  def colcount
    if ! defined? @colcount
      #p "not defined"
      for col in 1 .. 10000 do
        if describe(col) == nil then
          @colcount = col-1
          break
        end
      end
    end
    return  @colcount
  end
  def coltypemap(col)
    #return 1 #TORIAEZU
    case d=describe(col)[1]
    when
      Oracle::NUMBER,
      Oracle::VARCHAR2,
      Oracle::DATE,
      Oracle::CHAR,
      Oracle::LONG,
      Oracle::LONG_RAW
        Oracle::VARCHAR2
    else d
    end
  end
  def getCol2(col)
    a=getCol(col)
    d=describe(col)
    #p [col, d, a]
    if a[0]
      case d[1]
      when
        Oracle::NUMBER
          if (d[4] != 0) && (d[5] == 0)
            a[0]=a[0].to_i
          else
            a[0]=a[0].to_f
          end
      end
    end
    a
  end
end

module ORA_RDBC1

  include RDBC1

  # Driver Creator will inherite me.
  class ORA_ConnectionBridge < ConnectionBridge
    attr :ora_con
    def initialize(con)
      super
      #hostname=(con.prop["HOSTNAME"] || "localhost")
      #ipport=(con.prop["IPPORT"] || "5432")
      @ora_con = ORAconn.new(con.prop["USER"], con.prop["PASSWD"],
          con.prop["DBNAME"],)
    end
    def commit; @ora_con.commit; end
    def rollback; @ora_con.rollback; end
    def close
      super
      @ora_con.logoff
      @ora_con=nil
      #p "ora_con closed."
    end
  end

  class ORA_StatementBridge < StatementBridge
    attr :ora_cur
    def initialize(st)
      super
      @ora_cur=st.con.bridge.ora_con.open
      if st.sql
        #p "early parse"
        ora_cur.parse(st.sql)
      end
      @param = Hash[]
    end
    def execute(sql)
      #if @resultset; @resultset.close; end
      @resultset=nil
      if sql
        #p "late parse"
        ora_cur.parse(sql)
      end
      for col in 1..ora_cur.colcount do
        d=ora_cur.describe(col)
        #p [col, d]
        ora_cur.define(col, d[3], ora_cur.coltypemap(col))
      end
      #p [@sql, sql]
      a=ora_cur.exec
      if a
        @updatecount=a
        @resultset=Object.new #dummy
      else
        @updatecount=-1
        @resultset=Object.new #dummy
      end
    end
    def setParam(index, data)
      #p [index, data]
      a=data.to_s.dup
      @param[index.to_s]=a
      ora_cur.bindrv(index.to_s, a)
    end
    def close
      super
      @resultset=nil
      @ora_cur.close
      @ora_cur=nil
      @param=nil
    end
  end

  class ORA_ResultSetBridge < ResultSetBridge
    attr :ora_cur
    def initialize(rs)
      super
      @ora_cur=parent.statement.bridge.ora_cur
    end
    def close
      super
      #do nothing more.
    end
    def next
      if @ora_cur.fetch; true ;else; false; end
    end
    def getData(col=nil)
      if (col.is_a?(Integer))
        @ora_cur.getCol2(col+1)[0]
      elsif (col==nil)
        a=[]
        for col in 1..@ora_cur.colcount do
          a.push @ora_cur.getCol2(col)[0]
        end
        a
      end
      #String is decoded to Integer by ResultSet
    end
  end

  class ORA_ResultSetMetaDataBridge < ResultSetMetaDataBridge
    def columncount
      parent.parent.bridge.ora_cur.colcount
    end
    def columnName(index)
      a=parent.parent.bridge.ora_cur.describe(index+1)
      a[2].dup
    end
    def columnIndex(name)
      cur=parent.parent.bridge.ora_cur
      idx=nil
      for idx in 0..columncount-1 do
        a=columnName(idx)
        if a==name; break; end
      end
      idx
    end
  end

  # Driver Creator will inherite me.
  class ORA_Driver < Driver
    def url2prop(url)
      # Driver Creator will override me.
      super
    end
    def getConnectionBridgeClass
      # Driver Creator will override me.
      ORA_ConnectionBridge
    end
    def getStatementBridgeClass
      # Driver Creator will override me.
      ORA_StatementBridge
    end
    def getResultSetBridgeClass
      # Driver Creator will override me.
      ORA_ResultSetBridge
    end
    def getResultSetMetaDataBridgeClass
      # Driver Creator will override me.
      ORA_ResultSetMetaDataBridge
    end
    def preparable?
      true
    end
  end

  ORA_Driver.new
end


if $0 == __FILE__ #debug runner
  p "test start"

  #install your Driver
  include ORA_RDBC1
  #dr=ORA_Driver.new

  url="rdbc:ORA_Driver://localhost/"
  loginprops={"USER","nakamura", "PASSWD", "akifumi"}

  #You can choice 1 of 4 lines below to get a Connection instance.
  #co=dr.connect(url, loginprops)
  #co=DriverManager.getConnection(url, loginprops)
  #co=Connection.connect(url, loginprops)
  co=Connection.new(url, loginprops)

=begin
test table is:
  desc emp
 ------------------------------- -------- ----
  EMPNO                           NOT NULL NUMBER(4)
  ENAME                                    CHAR(10)
  JOB                                      CHAR(9)
  MGR                                      NUMBER(4)
  HIREDATE                                 DATE
  SAL                                      NUMBER(7,2)
  COMM                                     NUMBER(7,2)
  DEPTNO                          NOT NULL NUMBER(2)
=end

  st=co.createStatement("select * from emp where JOB = :a")

  [1, 2].each{ |i|
    p "----------------"
    st.setParam(":a", "CLERK")
    #st.execute; rs=st.resultset
    rs=st.executeQuery

    names=[]
    p rs.metadata.columncount
    for n in 0 ... rs.metadata.columncount
      names.push rs.metadata.columnName(n)
    end
    p names

    #xxx=[]
    while rs.next
      p "----"
      #p rs.data
      #p rs.data(0)
      #p rs.data("EMPNO")
      #xxx << rs.data([0,1,2,3,4,5,6,7])
      print '"', rs.data(["EMPNO", "ENAME", "JOB", "MGR", "HIREDATE", "SAL", "COMM", "DEPTNO"]).join('","'), '"', "\n"
    end
    #p xxx
  }

  #st=co.createStatement
  #p st.executeUpdate("update emp set sal='1111.2' where ename='ADAMS'")
  #st=co.createStatement("update emp set sal='1111.3' where ename=:abc")
  #st.setParam("abc", "ADAMS")
  #p st.executeUpdate
  #p st.updatecount

  #co.showtree

  p "test end"
end





