Archive for the ‘sqlserver’ Category

SQL Server Adapter for Rails 2.0

Thursday, December 13th, 2007

UPDATE: Everything works now. Turns out I had a plugin installed that monkey patched the SQL Server Adapter. This plugin was from an older version of Rails, and the Rails 2.0 adapters now extend from AbstractAdapter. Fixing the parent class in my plugin monkey patch (to extend from AbstractAdapter) fixed this up and now I no longer get the error.

I just installed the SQL Server Adapter Gem from gems.rubyonrails.org for my new Rails 2.0 project:


gem install activerecord-sqlserver-adapter --source=http://gems.rubyonrails.org

When I attempt to use it, I receive this error message:


TypeError: superclass mismatch for class SQLServerAdapter
        from /var/lib/gems/1.8/gems/activerecord-sqlserver-adapter-1.0.0/lib/active_record/connection_adapters/sqlserver_adapter.rb:190
        from /usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
        from /usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `require'
        from /home/sladd/development/workspace/DSES2/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:496:in `require'
        from /home/sladd/development/workspace/DSES2/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:342:in `new_constants_in'

Any ideas? My database.yml looks like this:


development:
  adapter: sqlserver
  mode: odbc
  dsn: dses_rollup
  username: sa
  password:

Has anyone successfully installed the new SQL Server adapter as a gem into a Rails 2.0 project?

I’ve asked the Ruby on Rails Talk Google Group, so we’ll see if that turns up any help.

Fixing Rails Pagination for SQL Server

Tuesday, July 31st, 2007

MS SQL Server certainly feels like the red headed step child of the Rails connection adapters. The core developers aren’t interested in it, and I’d have to guess that most Rails developers deploy to MySQL or PostgreSQL.

A good example of why the SQL Server support needs more love from the Rails community. The pagination code in the connection adapter is horribly ugly. SQL Server 2000 doesn’t support a limit or offset, which makes pagination extremely difficult. For kicks, check out the SQL that the Rails connection adapter generates for a limit and offset query in SQL Server. There’s enough sub queries and reverse sorts to make your head spin. Not to mention the awful performance killing select count(*) before every query.

SQL Server 2005 makes our life a little easier in that it added row_number() support. With this, it’s possible, however not straight forward, to perform pagination that doesn’t make you want to puke so much. Unfortunately, Rails hasn’t yet split their SQL Server adapters into a SQL Server 2000 and SQL Server 2005 adapters. I strongly encourage this move, as there are many differences between the two.

If you are running SQL Server 2005, and you want to fix many pagination problems that plague the sqlserver_adapter.rb (just look inside the Rails Trac sometime, there’s a lot), have I got the monkey patch for you. We’ve been using this for a little while now, and it seems to do the trick. YMMV but it should hopefully give you an idea of what’s possible.

module ActiveRecord
  module ConnectionAdapters
    class SQLServerAdapter

      def add_limit_offset!(sql, options)
        if options[:limit] and options[:offset]
          options[:order] ||= sql.match('FROM (.*) ')[1] + '.id'
          sql.sub!(/ORDER BY.*$/i, '')
          sql.sub!(/SELECT/i,
                  "SELECT row_number() over( order by #{options[:order]} ) as row_num, n")
          sql.replace("select top #{options[:limit]} * from (#{sql}) as tmp_table1 n" +
                "where row_num > #{options[:offset]}")
        end
      end
    end
  end
end

Not only was the built in pagination queries terribly slow (because it always executes a select count(*) before the query itself), but it had problems when doing paginations with included models. This is something that ActiveScaffold does all the time, so if you are using that and SQL Server, you’ve no doubt felt the pain when you tried to sort a column.

Locking Rows in SQL Server 2005

Friday, December 8th, 2006

There turns out to be a few different ways to lock rows in SQL Server 2005.

The `SERIALIZABLE` tag is one of the options. Here are a few more:

SQL Server Row Locking Strategies

As an aside, Rails (and Hibernate) support object locking with database locking semantics. In Rails 1.1.x, only optimistic locking was supported. Rails 1.2 added support for pesimistic locking.

Hibernate accomplishes the row lock with:

return tableName + ” with (updlock, rowlock)”;

AFAICT, Rails punts on this. I can’t find the locking syntax in the connection adapter. There is an add_lock! But it expects the locking syntax string unless you can use the default (`FOR UPDATE`, which of course SQL Server doesn’t support). That’s pretty lame on Rails’ part. But anyway…