⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sqlrelay.rb

📁 适合于Unix/Linux下的一个持久数据库连接池
💻 RB
字号:
# # DBD::SQLRelay# $Id: SQLRelay.rb,v 1.2 2004/02/15 17:59:45 mused Exp $# # Version : 0.1# Author  : Michael Neumann (neumann@s-direktnet.de)## Copyright (c) 2001 Michael Neumann## This program is free software; you can redistribute it and/or# modify it under the terms of the GNU General Public License# as published by the Free Software Foundation; either version 2# of the License, or (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the# GNU General Public License for more details.# # You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.require "sqlrelay"module DBImodule DBDmodule SQLRelayVERSION          = "0.1"USED_DBD_VERSION = "0.1"class Driver < DBI::BaseDriver  def initialize    super(USED_DBD_VERSION)  end  def connect(dbname, user, auth, attr)    # connect to database        # dbname will have one of these formats:    # * dbi:SQLRelay:host:port    # * dbi:SQLRelay:host=xxx;port=xxx;socket=xxx;retrytime=xxx;tries=xxx    hash = Utils.parse_params(dbname)    if hash.has_key? "database" then      # handle the first form      hash["host"], hash["port"] = hash["database"], hash["host"]    end    # set default values if none were supplied    hash['host']      ||= "localhost"    hash['port']      ||= "9000"    hash['socket']    ||= ""    hash['retrytime'] ||= "0"    hash['tries']     ||= "1"        # TODO: what happens on connection failure? return nil?    handle = SQLRConnection.new(hash['host'], hash['port'].to_i,       hash['socket'], user, auth, hash['retrytime'].to_i, hash['tries'].to_i)    return Database.new(handle, attr)  endend # class Driverclass Database < DBI::BaseDatabase  def disconnect    @handle.endSession  end  def ping    @handle.ping == 1 ? true : false  end  def prepare(statement)    Statement.new(@handle, statement)  end  def commit    $stderr.puts "Warning: Commit ineffective while AutoCommit is on" if @attr['AutoCommit']    case @handle.commit    when 0      # failed      raise DBI::OperationalError.new("Commit failed")    when -1      raise DBI::OperationalError.new("Error occured during commit")   end  end  def rollback    $stderr.puts "Warning: Rollback ineffective while AutoCommit is on" if @attr['AutoCommit']    case @handle.rollback    when 0      # failed      raise DBI::OperationalError.new("Rollback failed")    when -1      raise DBI::OperationalError.new("Error occured during rollback")    end  end  def []=(attr, value)    # AutoCommit and sqlrelay_debug are supported by this driver    case attr    when 'AutoCommit'      if value == true        @handle.autoCommitOn      else        @handle.autoCommitOff      end    when 'sqlrelay_debug'       if value == true        @handle.debugOn      else        @handle.debugOff      end    else      if attr =~ /^sqlrelay_/ or attr != /_/        # raise and exception for unsupported or improperly formatted options        raise DBI::NotSupportedError, "Option '#{attr}' not supported"      else         # option for some other driver - quietly ignore        return        end         end    @attr[attr] = value  endend # class Databaseclass Statement < DBI::BaseStatement  def initialize(handle, stmt)    super(nil)  # attribs    @db = handle     @handle = SQLRCursor.new(@db)    @handle.setResultSetBufferSize(100)    @handle.prepareQuery(stmt)  end  def bind_param(param, value, attribs)    # in SQL Relay, bind variable names can be names or numbers and values    # can be either strings, integers or floats.  Floats come with precision    # and scale as well.    if value.kind_of? Float then      # for float binds, check attribs for precision and scale      if attribs        precision = attribs['precision'].to_i        scale     = attribs['scale'].to_i      end      # if either of precision or scale is not passed in, extract them by      # parsing the value around the decimal point or using defaults      if precision.nil? or scale.nil?        pr, sc = value.to_s.split(".")        precision ||= pr.length || 8        scale     ||= sc.length || 2      end      @handle.inputBind(param.to_s, value.to_f, precision, scale)    else      @handle.inputBind(param.to_s, value)    end  end  def execute    # otherwise execute the already-prepared query, raising an error if it fails    if @handle.executeQuery == 0 then       raise DBI::ProgrammingError.new(@handle.errorMessage)    end    # initialize some values    @row_index = 0    @row_count = @handle.rowCount    @affected_rows = @handle.affectedRows    # clear bind values so the statement can be re-bound and re-executed    @handle.clearBinds  end  def finish    @handle = nil  end  def fetch    # if we're already at the end of the result set, return nil    if @row_index >= @row_count       return nil    end    # otherwise get the current row, increment    # the row index and return the current row    row = @handle.getRow(@row_index)    @row_index += 1    return row  end  def fetch_scroll(direction, offset=1)    # decide which row to fetch, take into account that the standard behavior    # of a fetch command is to fetch the row and then skip to the next row    # of the result set afterward    fetch_row = case direction      when DBI::SQL_FETCH_NEXT     then @row_index      when DBI::SQL_FETCH_PRIOR    then @row_index-2      when DBI::SQL_FETCH_FIRST    then 0      when DBI::SQL_FETCH_LAST     then @row_count-1      when DBI::SQL_FETCH_ABSOLUTE then offset      when DBI::SQL_FETCH_RELATIVE then @row_index+offset-1    end        # fetch the row    row = nil    if fetch_row > -1 and fetch_row < @row_count      row = @handle.getRow(fetch_row)    end    # set the current row, avoid running past     # the end or beginning of the result set    @row_index = fetch_row + 1    if @row_index < 0 then      @row_index = 0    elsif @row_index > @row_count      @row_index = @row_count    end    return row  end  def fetch_many(cnt)    # fetch the next "cnt" rows and return them    *rows = []    index = 0    while index < cnt and @row_index < @row_count      *rows[index] = fetch()      index = index+1    end    return *rows  end  def fetch_all    # otherwise, fetch the rest of the rows and return them    *rows = []    index = 0    while @row_index < @row_count      *rows[index] = fetch()      index = index+1    end    return *rows  end  def column_info    # build a column info hash    (0...@handle.colCount).collect do |nr|      {        'name'      => @handle.getColumnName(nr),        'type_name' => @handle.getColumnType(nr),        'precision' => @handle.getColumnLength(nr)      }    end  end  def rows    # For DML or DDL queries, row_count is 0 but affected_rows could    # be non-zero.  For selects, affected_rows will always be zero or    # equal to row_count (for select into queries, for example).  So,    # if row_count is 0, send affected_rows.    @row_count == 0 ? @affected_rows : @row_count  endend # class Statementend # module SQLRelayend # module DBDend # module DBI

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -