`
kiol
  • 浏览: 43397 次
  • 来自: ...
社区版块
存档分类
最新评论

rails中使用SQLServer的最简单有效解决方案

阅读更多

其实很简单,我把ADO.rb给改了,加了编码转换,这样rails端使用起来就不需要做太特殊修改了。

#
# DBD::ADO
#
# Copyright (c) 2001, 2002 Michael Neumann <neumann@s-direktnet.de>
# 
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without 
# modification, are permitted provided that the following conditions 
# are met:
# 1. Redistributions of source code must retain the above copyright 
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright 
#    notice, this list of conditions and the following disclaimer in the 
#    documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
#    derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
# THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $Id$
#

require "win32ole"
require "iconv"

module DBI
module DBD
module ADO

VERSION          = "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

    handle = WIN32OLE.new('ADODB.Connection')
    handle.Open(dbname)
    handle.BeginTrans()  # start new Transaction

    return Database.new(handle, attr)
  rescue RuntimeError => err
    raise DBI::DatabaseError.new(@iconv_out.iconv(err.message))
  end

end

class Database < DBI::BaseDatabase
 
  def disconnect
    @handle.RollbackTrans()
    @handle.Close()
  rescue RuntimeError => err
    raise DBI::DatabaseError.new(@iconv_out.iconv(err.message))
  end

  def prepare(statement)
    # TODO: create Command instead?
    Statement.new(@handle, statement, self)
  end

  def commit
    # TODO: raise error if AutoCommit on => better in DBI?
    @handle.CommitTrans()
    @handle.BeginTrans()
  rescue RuntimeError => err
    raise DBI::DatabaseError.new(@iconv_out.iconv(err.message))
  end

  def rollback
    # TODO: raise error if AutoCommit on => better in DBI?
    @handle.RollbackTrans()
    @handle.BeginTrans()
  rescue RuntimeError => err
    raise DBI::DatabaseError.new(@iconv_out.iconv(err.message))
  end

  def []=(attr, value)
    if attr == 'AutoCommit' then
      # TODO: commit current transaction?
      @attr[attr] = value
    else
      super
    end
  end


end # class Database


class Statement < DBI::BaseStatement
  include SQL::BasicBind
  include SQL::BasicQuote

  def initialize(handle, statement, db)
    @iconv_in = Iconv.new('gb18030','utf-8')
    @iconv_out = Iconv.new('utf-8','gb18030')
    @handle = handle
    @statement = @iconv_in.iconv(statement)
    @params = []
    @db = db
  end

  def bind_param(param, value, attribs)
    raise InterfaceError, "only ? parameters supported" unless param.is_a? Fixnum

    @params[param-1] = value 
  end

  def execute
    # TODO: use Command and Parameter
    # TODO: substitute all ? by the parametes
    #sql = bind(self, @statement, @params)
    
    @res_handle = @handle.Execute(@statement) 

    # TODO: SELECT and AutoCommit finishes the result-set
    #       what to do?
    if @db['AutoCommit'] == true and not SQL.query?(@statement) then
      @db.commit
    end

  rescue RuntimeError => err
    raise DBI::DatabaseError.new(@iconv_out.iconv(err.message))
  end

  def finish
    # if DCL, DDL or INSERT UPDATE and DELETE, this gives an Error
    # because no Result-Set is available
    if @res_handle.Fields.Count() != 0 then
      @res_handle.Close()
    end
  rescue RuntimeError => err
    raise DBI::DatabaseError.new(err.message)
  end

  def fetch        
    retval = fetch_currentrow
    @res_handle.MoveNext() unless retval.nil?
    retval
  rescue RuntimeError => err
    raise DBI::DatabaseError.new(@iconv_out.iconv(err.message))
  end



  def fetch_scroll(direction, offset)
    case direction
    when DBI::SQL_FETCH_NEXT
      return fetch
    when DBI::SQL_FETCH_PRIOR
      # TODO: check if already the first?
      #return nil if @res_handle.AbsolutePosition()
      @res_handle.MovePrevious()
      return fetch_currentrow
    when DBI::SQL_FETCH_FIRST
      @res_handle.MoveFirst()
      return fetch_currentrow
    when DBI::SQL_FETCH_LAST
      @res_handle.MoveLast()
      return fetch_currentrow
    when DBI::SQL_FETCH_RELATIVE
      @res_handle.Move(offset)
      return fetch_currentrow
    when DBI::SQL_FETCH_ABSOLUTE
      ap = @res_handle.AbsolutePositon()      
      @res_handle.Move(offset-ap)
      return fetch_currentrow      
    else
      raise DBI::InterfaceError
    end    
  rescue RuntimeError => err
    raise DBI::DatabaseError.new(@iconv_out.iconv(err.message))
  end

  def column_info
    num_cols = @res_handle.Fields().Count()
    retval = Array.new(num_cols)

    for i in 0...num_cols do
      retval[i] = {'name' => @iconv_out.iconv(@res_handle.Fields(i).Name())}
    end

    retval
  rescue RuntimeError => err
    raise DBI::DatabaseError.new(@iconv_out.iconv(err.message))
  end

  def rows
    # TODO: how to get the RPC in ADO? 
    nil
  end

  
  private

  def fetch_currentrow    
    return nil if @res_handle.EOF() or @res_handle.BOF()
      
    # TODO: don't create new Array each time
    num_cols = @res_handle.Fields().Count()
    retval = Array.new(num_cols)

    for i in 0...num_cols do
      if @res_handle.Fields(i).Value().is_a? String
        retval[i] = @iconv_out.iconv(@res_handle.Fields(i).Value())
      else
        retval[i] = @res_handle.Fields(i).Value()
      end
    end
  
    retval
  end
  

end


end # module ADO
end # module DBD
end # module DBI

 用上面的文件内容替换掉原来的ADO.rb。如果你没装过ADO.rb,直接把内容另存为ruby\lib\ruby\site_ruby\1.8\DBD\ADO\ADO.rb就可以了。

分享到:
评论

相关推荐

    rails配置sqlserver2000

    在Ruby on Rails框架中,与SQLServer 2000集成可能会比与其他常见的数据库系统(如MySQL或PostgreSQL)稍复杂一些,因为SQLServer 2000的兼容性问题和缺少官方支持。然而,通过一些第三方库和适当的配置,我们仍然...

    Ruby-SQLServerRailsActiveRecord的SQLServer适配器

    本主题将深入探讨如何在Rails应用中使用SQL Server作为数据存储,特别关注`activerecord-sqlserver-adapter`这个gem,它使得Ruby的ActiveRecord能够与Microsoft SQL Server无缝集成。 `activerecord-sqlserver-...

    网上书城struts+jsp+SqlServer源代码

    Struts、JSP和SQL Server是构建Web应用程序的常用技术栈,它们在“网上书城”项目中的结合展示了如何利用这些技术实现一个完整的电子商务平台。本文将深入探讨这些技术及其在实际项目中的应用。 首先,Struts是一个...

    rails中使用javascript日期控件

    这篇博客“rails中使用javascript日期控件”探讨的就是如何在Rails应用中集成JavaScript日期控件,特别是通过一个名为WebCalendar.js的库来实现这一功能。WebCalendar.js是一个轻量级的JavaScript库,用于创建交互式...

    提升Ruby on Rails性能的几个解决方案

    简介 Ruby On Rails 框架自它提出之日...Rails 是一个真正彻底的 MVC(Model-View-Controller) 框架,Rails 清楚地将你的模型的代码与你的控制器的应用逻辑从 View 代码中分离出来。Rails 开发人员很少或者可能从未遇到

    Ruby on Rails中文指南

    Ruby on Rails使用ActiveRecord,一个ORM(对象关系映射)库,使得与数据库交互变得简单。你可以通过定义类和方法来创建、更新、查询数据。 3. **视图(Views)**:视图负责呈现用户界面。它们通常由HTML、CSS和...

    使用Aptana+Rails开发Rails Web应用(中文)

    为了运行和测试应用,你需要在命令行中使用Rails服务器。在Aptana中,可以使用内置的终端工具。打开“Terminal”视图,输入`rails server`启动服务器,然后在浏览器中访问`http://localhost:3000`查看你的应用。 在...

    在Rails中使用SSL

    标题“在Rails中使用SSL”涉及的是如何在Ruby on Rails框架下配置并使用安全套接层(SSL)来实现网站的加密通信。Rails是用Ruby编程语言开发的一个流行的Web应用程序框架,它支持HTTPS协议,通过SSL/TLS证书来提供...

    Rails项目源代码

    这个“Rails项目源代码”是一个使用Rails构建的图片分享网站的完整源代码,它揭示了如何利用Rails的强大功能来创建一个允许用户上传、分享和浏览图片的应用。 1. **Rails框架基础**: Rails的核心理念是DRY(Don't...

    Rails3 使用rake启动后台任务

    以下是一些关于如何在 Rails3 中使用 rake 启动后台任务的知识点: 1. **Rakefile**: 每个 Rails 项目都有一个 Rakefile 文件,这是 Rake 执行任务的入口点。在这个文件中,你可以定义自定义的任务。 2. **Task ...

    rails指南 中文版

    通过ActiveRecord,开发者可以使用面向对象的方式来操作数据,而无需编写SQL语句。 2. **ActionController**:负责处理HTTP请求并生成HTTP响应。控制器是MVC架构中的C,它连接模型和视图,处理用户输入,调用模型...

    Rails

    描述中提到的博文链接指向了一个ITEYE博客文章,尽管具体内容未提供,但通常这样的博客可能会包含Rails的使用技巧、最佳实践、新版本更新或者特定问题的解决方案。 标签 "源码" 暗示了可能涉及Rails的源代码分析或...

    shoppe-example, 在 Rails 中使用Shoppe平台的示例存储实现.zip

    shoppe-example, 在 Rails 中使用Shoppe平台的示例存储实现 这是一个 Rails 应用程序,它使用 Shoppe 构建。 它具有一个可以爱的设计,以充分演示Shoppe平台提供的功能以及它在 Rails 应用程序中的。 正在启动要开始...

    activerecord-sqlserver-adapter:用于RailsSQL Server适配器

    迁移中的所有简化的Rails类型都将与匹配SQL Server国家(unicode)数据类型相对应。 始终检查initialize_native_database_types 以获取更新的列表。 以下类型( date , datetime2 , datetimeoffset ,

    rails-assets, 在 Rails 中,资产管理的解决.zip

    rails-assets, 在 Rails 中,资产管理的解决 Rails 资产 Bundler 到 Bower 代理本自述文件涉及项目的开发方面。 访问站点了解如何在你的应用程序中使用 Rails 资产。 插件开发设置git clone git@github.com:tenex/r

    Rails的中文乱码问题

    标题中的“Rails的中文乱码问题”涉及到的是在使用Ruby on Rails框架开发Web应用时,遇到的中文字符编码不正确的问题。Rails是一个基于Ruby语言的开源Web开发框架,它遵循MVC(Model-View-Controller)架构模式。在...

    rails飞信 gem plugin api 插件的问题解决方案

    标题中的“rails飞信 gem plugin api 插件的问题解决方案”涉及到的是在Ruby on Rails框架下,使用特定的gem(一种Ruby的库或插件)来集成飞信API时遇到的问题及解决方法。飞信是中国移动推出的一种即时通讯服务,...

    Ruby On Rails中文教材(PDF)

    4. **ActiveRecord**:这是Rails中的ORM(对象关系映射)库,它允许开发者用Ruby代码操作数据库,无需编写SQL。 5. **Scaffolding**:Rails的快速开发工具,能自动生成CRUD(创建、读取、更新、删除)操作的模型、...

Global site tag (gtag.js) - Google Analytics