-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tinytds adapter, the best way to connect to MSSQL from a C based …
…ruby running on *nix Before, the only real way to connect to MSSQL from a C based ruby on *nix was to use the ODBC adapter with unixodbc and freetds. I've heard it's a big pain to set up, and never attempted to do so myself. Fortunately, tiny_tds was released recently and makes it simple. Thanks to metaskills from the tiny_tds project for making changes to tiny_tds to better support Sequel.
- Loading branch information
1 parent
b81bdca
commit 7b645ed
Showing
8 changed files
with
162 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
require 'tiny_tds' | ||
Sequel.require 'adapters/shared/mssql' | ||
|
||
module Sequel | ||
module TinyTDS | ||
class Database < Sequel::Database | ||
include Sequel::MSSQL::DatabaseMethods | ||
set_adapter_scheme :tinytds | ||
|
||
# Transfer the :host and :user options to the | ||
# :dataserver and :username options. | ||
def connect(server) | ||
opts = server_opts(server) | ||
opts[:dataserver] = opts[:host] | ||
opts[:username] = opts[:user] | ||
TinyTds::Client.new(opts) | ||
end | ||
|
||
# Return instance of Sequel::TinyTDS::Dataset with the given options. | ||
def dataset(opts = nil) | ||
TinyTDS::Dataset.new(self, opts) | ||
end | ||
|
||
# Execute the given +sql+ on the server. If the :return option | ||
# is present, its value should be a method symbol that is called | ||
# on the TinyTds::Result object returned from executing the | ||
# +sql+. The value of such a method is returned to the caller. | ||
# Otherwise, if a block is given, it is yielded the result object. | ||
# If no block is given and a :return is not present, +nil+ is returned. | ||
def execute(sql, opts={}) | ||
synchronize(opts[:server]) do |c| | ||
begin | ||
m = opts[:return] | ||
r = nil | ||
log_yield(sql) do | ||
r = c.execute(sql) | ||
return r.send(m) if m | ||
end | ||
yield(r) if block_given? | ||
rescue TinyTds::Error => e | ||
raise_error(e) | ||
ensure | ||
r.cancel if r && c.sqlsent? | ||
end | ||
end | ||
end | ||
|
||
# Return the number of rows modified by the given +sql+. | ||
def execute_dui(sql, opts={}) | ||
execute(sql, opts.merge(:return=>:do)) | ||
end | ||
|
||
# Return the value of the autogenerated primary key (if any) | ||
# for the row inserted by the given +sql+. | ||
def execute_insert(sql, opts={}) | ||
execute(sql, opts.merge(:return=>:insert)) | ||
end | ||
|
||
# Execute the DDL +sql+ on the database and return nil. | ||
def execute_ddl(sql, opts={}) | ||
execute(sql, opts.merge(:return=>:each)) | ||
nil | ||
end | ||
|
||
private | ||
|
||
# For some reason, unless you specify a column can be | ||
# NULL, it assumes NOT NULL, so turn NULL on by default unless | ||
# the column is a primary key column. | ||
def column_list_sql(g) | ||
pks = [] | ||
g.constraints.each{|c| pks = c[:columns] if c[:type] == :primary_key} | ||
g.columns.each{|c| c[:null] = true if !pks.include?(c[:name]) && !c[:primary_key] && !c.has_key?(:null) && !c.has_key?(:allow_null)} | ||
super | ||
end | ||
|
||
# Close the TinyTds::Client object. | ||
def disconnect_connection(c) | ||
c.close | ||
end | ||
end | ||
|
||
class Dataset < Sequel::Dataset | ||
include Sequel::MSSQL::DatasetMethods | ||
|
||
# Yield hashes with symbol keys, attempting to optimize for | ||
# various cases. | ||
def fetch_rows(sql) | ||
execute(sql) do |result| | ||
each_opts = {:cache_rows=>false} | ||
each_opts[:timezone] = :utc if Sequel.database_timezone == :utc | ||
offset = @opts[:offset] | ||
@columns = cols = result.fields.map{|c| output_identifier(c)} | ||
if identifier_output_method | ||
each_opts[:as] = :array | ||
result.each(each_opts) do |r| | ||
h = {} | ||
cols.zip(r).each{|k, v| h[k] = v} | ||
h.delete(row_number_column) if offset | ||
yield h | ||
end | ||
else | ||
each_opts[:symbolize_keys] = true | ||
if offset | ||
result.each(each_opts) do |r| | ||
r.delete(row_number_column) if offset | ||
yield r | ||
end | ||
else | ||
result.each(each_opts, &block) | ||
end | ||
end | ||
end | ||
self | ||
end | ||
|
||
private | ||
|
||
# Properly escape the given string +v+. | ||
def literal_string(v) | ||
db.synchronize{|c| "N'#{c.escape(v)}'"} | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters