tiny_tds 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ Makefile
2
+ *.dSYM
3
+ *.o
4
+ *.bundle
5
+ *.so
6
+ *.a
7
+ *.rbc
8
+ mkmf.log
9
+ pkg/
10
+ tmp
11
+ vendor
12
+ lib/tiny_tds/tiny_tds.rb
13
+ .rvmrc
14
+ Gemfile.lock
15
+ misc
16
+ *.gem
17
+ ports
data/CHANGELOG CHANGED
@@ -1,4 +1,9 @@
1
1
 
2
+ * 0.4.4 *
3
+
4
+ * New :host/:port connection options. Removes need for freetds.conf file.
5
+
6
+
2
7
  * 0.4.3 *
3
8
 
4
9
  * New Client#active? method to check for good connection. Always use this abstract method.
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+
2
+ source :rubygems
3
+
4
+ group :development do
5
+ gem 'rake', '>= 0.8.7'
6
+ gem 'mini_portile', '0.2.1'
7
+ gem 'rake-compiler', '0.7.7'
8
+ end
9
+
10
+ group :test do
11
+ gem 'mini_shoulda'
12
+ gem 'activesupport', '2.3.5'
13
+ gem 'bench_press', '0.3.1'
14
+ platforms :mri_18 do
15
+ gem 'ruby-prof', '0.9.1'
16
+ gem 'ruby-debug', '0.10.3'
17
+ end
18
+ end
data/NOTES ADDED
@@ -0,0 +1,14 @@
1
+
2
+ TODO
3
+
4
+ * Update Readme when 0.83.dev becomes a release.
5
+
6
+ * Client & Connection
7
+ - Make a #ping method that does the "SELECT 1" when not closed.
8
+ - Interrupt handler to cancel a bad SELECT * or long SQL. Maybe use dbsetinterrupt
9
+ - Integrate rb_thread_blocking_region where we can in your extension for proper threading in 1.9.2
10
+
11
+ * Result Set
12
+ - See if we can make a binary string of [timestamp] type.
13
+
14
+
data/README.rdoc CHANGED
@@ -14,8 +14,9 @@ The API is simple and consists of these classes:
14
14
 
15
15
  == New & Noteworthy
16
16
 
17
- * Works with FreeTDS 0.83.dev
17
+ * Works with FreeTDS 0.91
18
18
  * Tested on Windows using MiniPortile & RailsInstaller.
19
+ * New :host/:port connection options. Removes need for freetds.conf file.
19
20
 
20
21
 
21
22
  == Install
@@ -30,7 +31,7 @@ Although we search for FreeTDS's libraries and headers, you may have to specify
30
31
 
31
32
  == FreeTDS Compatibility
32
33
 
33
- TinyTDS is developed for FreeTDS 0.82 & 0.83.dev. It is tested with SQL Server 2000, 2005, 2008 and Azure using TDS Version 8.0. We utilize FreeTDS's db-lib client library. We compile against sybdb.h, undefine MSDBLIB and define SYBDBLIB which means that internally we conform to sybase API to db-lib. TinyTDS will work for both Sybase & Miscrosoft SQL Server. You do NOT need to compile FreeTDS with the "--enable-msdblib" option for our client to work properly. However, please make sure to compile FreeTDS with libiconv support for encodings to work at their best. Run "tsql -C" in your console and check for "iconv library: yes".
34
+ TinyTDS is developed for FreeTDS 0.82 & 0.91. It is tested with SQL Server 2000, 2005, 2008 and Azure using TDS Version 8.0. We utilize FreeTDS's db-lib client library. We compile against sybdb.h, undefine MSDBLIB and define SYBDBLIB which means that internally we conform to sybase API to db-lib. TinyTDS will work for both Sybase & Miscrosoft SQL Server. You do NOT need to compile FreeTDS with the "--enable-msdblib" option for our client to work properly. However, please make sure to compile FreeTDS with libiconv support for encodings to work at their best. Run "tsql -C" in your console and check for "iconv library: yes".
34
35
 
35
36
 
36
37
 
@@ -51,13 +52,15 @@ Below is a list of the data types we plan to support using future versions of Fr
51
52
 
52
53
  Connect to a database.
53
54
 
54
- client = TinyTds::Client.new(:username => 'sa', :password => 'secret', :dataserver => 'mytds_box')
55
+ client = TinyTds::Client.new(:username => 'sa', :password => 'secret', :host => 'mydb.host.net')
55
56
 
56
57
  Creating a new client takes a hash of options. For valid iconv encoding options, see the output of "iconv -l". Only a few have been tested and highly recommended to leave blank for the UTF-8 default.
57
58
 
58
59
  * :username - The database server user.
59
60
  * :password - The user password.
60
61
  * :dataserver - The name for your server as defined in freetds.conf.
62
+ * :host - Used if :dataserver blank. Removes need for freetds.conf file.
63
+ * :port - Defaults to 1433. Only used if :host is used.
61
64
  * :database - The default database to use.
62
65
  * :appname - Short string seen in SQL Servers process/activity window.
63
66
  * :tds_version - TDS version. Defaults to 80, not recommended to change.
@@ -222,7 +225,7 @@ By default row caching is turned on because the SQL Server adapter for ActiveRec
222
225
 
223
226
  == Using TinyTDS With Rails & The ActiveRecord SQL Server adapter.
224
227
 
225
- As of version 2.3.11 & 3.0.3 of the adapter, you can specify a :dblib mode in database.yml and use TinyTDS as the low level connection mode. Make sure to add a :dataserver option to that matches the name in your freetds.conf file. The SQL Server adapter can be found using the link below. Also included is a direct link to the wiki article covering common questions when using TinyTDS as the low level connection mode for the adapter.
228
+ As of version 2.3.11 & 3.0.3 of the adapter, you can specify a :dblib mode in database.yml and use TinyTDS as the low level connection mode. The SQL Server adapter can be found using the link below. Also included is a direct link to the wiki article covering common questions when using TinyTDS as the low level connection mode for the adapter.
226
229
 
227
230
  http://github.com/rails-sqlserver/activerecord-sqlserver-adapter/wiki/Using-TinyTds
228
231
 
@@ -230,7 +233,7 @@ http://github.com/rails-sqlserver/activerecord-sqlserver-adapter/wiki/Using-Tiny
230
233
 
231
234
  == Using TinyTDS with Azure
232
235
 
233
- TinyTDS is fully tested with the Azure platform. You must set the :azure => true connection option when connecting. This is needed to specify the default in the login packet since Azure has no notion of "USE [database]". You must use the latest FreeTDS 0.83.dev and it must be compiled with OpenSSL.
236
+ TinyTDS is fully tested with the Azure platform. You must set the :azure => true connection option when connecting. This is needed to specify the default database name in the login packet since Azure has no notion of "USE [database]". You must use the latest FreeTDS 0.91. FreeTDS must be compiled with OpenSSL too.
234
237
 
235
238
 
236
239
 
@@ -239,6 +242,8 @@ TinyTDS is fully tested with the Azure platform. You must set the :azure => true
239
242
  We use bundler for development. Simply run "bundle install" then "rake" to build the gem and run the unit tests. The tests assume you have created a database named "tinytdstest" accessible by a database owner named "tinytds". Before running the test rake task, you may need to define a pair of environment variables that help the client connect to your specific FreeTDS database server name and which schema (2000, 2005, 2008 or azure) to use. For example:
240
243
 
241
244
  $ rake TINYTDS_UNIT_DATASERVER=mydbserver TINYTDS_SCHEMA=sqlserver_2008
245
+ or
246
+ $ rake TINYTDS_UNIT_HOST=mydb.host.net TINYTDS_SCHEMA=sqlserver_azure
242
247
 
243
248
  If you are compiling locally using MiniPortile (the default dev setup) and you do not have a user based freetds.conf file with your dataservers, you may have to configure the locally compiled freetds.conf file. You can find it at the ports/<platform>/freetds/<version>/etc/freetds.conf path locally to your repo. In this situation you may have to set the FREETDS environment variable too this full path.
244
249
 
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ # encoding: UTF-8
2
+ require 'rake'
3
+ require "rake/clean"
4
+ require 'rbconfig'
5
+ require 'rake/testtask'
6
+ require 'rake/extensiontask'
7
+ require "rubygems/package_task"
8
+
9
+ Dir["tasks/*.rake"].sort.each { |f| load f }
10
+
11
+ def test_libs
12
+ ['lib','test']
13
+ end
14
+
15
+ def test_files
16
+ Dir.glob("test/**/*_test.rb").sort
17
+ end
18
+
19
+ def gemspec
20
+ @clean_gemspec ||= eval(File.read(File.expand_path('../tiny_tds.gemspec', __FILE__)))
21
+ end
22
+
23
+ Rake::TestTask.new do |t|
24
+ t.libs = test_libs
25
+ t.test_files = test_files
26
+ t.verbose = true
27
+ end
28
+
29
+ Gem::PackageTask.new(gemspec) do |pkg|
30
+ pkg.need_tar = false
31
+ pkg.need_zip = false
32
+ end
33
+
34
+ task :compile => ["ports:freetds"] unless ENV['TINYTDS_SKIP_PORTS']
35
+
36
+ Rake::ExtensionTask.new('tiny_tds', gemspec) do |ext|
37
+ ext.lib_dir = 'lib/tiny_tds'
38
+ ext.config_options << "--enable-iconv" unless ENV['TINYTDS_SKIP_PORTS']
39
+ # Automatically add build options to avoid need of manual input.
40
+ if RUBY_PLATFORM =~ /mswin|mingw/ then
41
+ # Define target for extension (supporting fat binaries).
42
+ RUBY_VERSION =~ /(\d+\.\d+)/
43
+ ext.lib_dir = "lib/tiny_tds/#{$1}"
44
+ else
45
+ ext.cross_compile = true
46
+ ext.cross_platform = ['i386-mingw32']
47
+ ext.cross_config_options << "--disable-lookup"
48
+ ext.cross_config_options << "--with-iconv-dir=#{$recipes[:libiconv].path}"
49
+ ext.cross_config_options << "--with-freetds-dir=#{$recipes[:freetds].path}"
50
+ end
51
+ end
52
+
53
+ task :build => [:clean, :compile]
54
+
55
+ task :default => [:build, :test]
56
+
57
+
@@ -70,9 +70,14 @@ def have_freetds?
70
70
  find_freetds_libraries_path && find_freetds_include_path
71
71
  end
72
72
 
73
- unless have_freetds?
74
- abort "-----\nCan not find FreeTDS's db-lib or include directory.\n-----"
73
+ if enable_config("lookup", true)
74
+ unless have_freetds?
75
+ abort "-----\nCan not find FreeTDS's db-lib or include directory.\n-----"
76
+ end
77
+ else
78
+ unless have_freetds_libraries?(*FREETDS_LIBRARIES) && have_freetds_headers?(*FREETDS_HEADERS)
79
+ abort "-----\nCan not find FreeTDS's db-lib or include directory.\n-----"
80
+ end
75
81
  end
76
82
 
77
83
  create_makefile('tiny_tds/tiny_tds')
78
-
data/lib/tiny_tds.rb CHANGED
@@ -3,16 +3,17 @@ require 'date'
3
3
  require 'bigdecimal'
4
4
  require 'rational' unless RUBY_VERSION >= '1.9.2'
5
5
 
6
+ require 'tiny_tds/version'
6
7
  require 'tiny_tds/error'
7
8
  require 'tiny_tds/client'
8
9
  require 'tiny_tds/result'
9
10
 
10
- require 'tiny_tds/tiny_tds'
11
+ # support multiple ruby version (fat binaries under windows)
12
+ begin
13
+ RUBY_VERSION =~ /(\d+.\d+)/
14
+ require "tiny_tds/#{$1}/tiny_tds"
15
+ rescue LoadError
16
+ require 'tiny_tds/tiny_tds'
17
+ end
11
18
 
12
19
 
13
- # = TinyTds
14
- #
15
- # Tiny Ruby Wrapper For FreeTDS Using DB-Library
16
- module TinyTds
17
- VERSION = '0.4.3'
18
- end
@@ -47,13 +47,20 @@ module TinyTds
47
47
 
48
48
 
49
49
  def initialize(opts={})
50
- raise ArgumentError, 'missing :username option' if opts[:username].nil? || opts[:username].empty?
50
+ raise ArgumentError, 'missing :username option' if opts[:username].to_s.empty?
51
+ raise ArgumentError, 'missing :host option if no :dataserver given' if opts[:dataserver].to_s.empty? && opts[:host].to_s.empty?
51
52
  @query_options = @@default_query_options.dup
52
53
  opts[:appname] ||= 'TinyTds'
53
54
  opts[:tds_version] = TDS_VERSIONS_SETTERS[opts[:tds_version].to_s] || TDS_VERSIONS_SETTERS['80']
54
55
  opts[:login_timeout] ||= 60
55
56
  opts[:timeout] ||= 5
56
57
  opts[:encoding] = (opts[:encoding].nil? || opts[:encoding].downcase == 'utf8') ? 'UTF-8' : opts[:encoding].upcase
58
+ opts[:port] ||= 1433
59
+ ENV['TDSPORT'] = opts[:port].to_s
60
+ if opts[:dataserver].to_s.empty?
61
+ opts[:dataserver] = ''
62
+ ENV['TDSHOST'] = opts[:host].to_s
63
+ end
57
64
  connect(opts)
58
65
  end
59
66
 
@@ -0,0 +1,3 @@
1
+ module TinyTds
2
+ VERSION = '0.4.4'
3
+ end
data/tasks/ports.rake ADDED
@@ -0,0 +1,59 @@
1
+ require "mini_portile"
2
+ require "rake/extensioncompiler"
3
+
4
+ namespace :ports do
5
+
6
+ ICONV_VERSION = "1.13.1"
7
+ FREETDS_VERSION = ENV['TINYTDS_FREETDS_082'] ? "0.82" : "0.91"
8
+ FREETDS_VERSION_INFO = {
9
+ "0.82" => {:files => "http://ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable.tgz"},
10
+ "0.91" => {:files => "http://www.ibiblio.org/pub/Linux/ALPHA/freetds/current/freetds-current.tgz"} }
11
+
12
+ ORIGINAL_HOST = RbConfig::CONFIG["arch"]
13
+
14
+ directory "ports"
15
+
16
+ $recipes = {}
17
+ $recipes[:libiconv] = MiniPortile.new "libiconv", ICONV_VERSION
18
+ $recipes[:libiconv].files << "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-#{ICONV_VERSION}.tar.gz"
19
+
20
+ $recipes[:freetds] = MiniPortile.new "freetds", FREETDS_VERSION
21
+ $recipes[:freetds].files << FREETDS_VERSION_INFO[FREETDS_VERSION][:files]
22
+
23
+ desc "Compile libiconv support library"
24
+ task :libiconv => ["ports"] do
25
+ recipe = $recipes[:libiconv]
26
+ checkpoint = "ports/.#{recipe.name}.#{recipe.version}.#{recipe.host}.timestamp"
27
+ unless File.exist?(checkpoint)
28
+ recipe.cook
29
+ touch checkpoint
30
+ end
31
+ recipe.activate
32
+ end
33
+
34
+ desc "Compile freetds library"
35
+ task :freetds => ["ports", :libiconv] do
36
+ recipe = $recipes[:freetds]
37
+ checkpoint = "ports/.#{recipe.name}.#{recipe.version}.#{recipe.host}.timestamp"
38
+ unless File.exist?(checkpoint)
39
+ recipe.configure_options << "--disable-odbc"
40
+ recipe.configure_options << "--with-tdsver=7.1"
41
+ # HACK: Only do this when cross compiling (util MiniPortile#activate gets the job done)
42
+ unless recipe.host == ORIGINAL_HOST
43
+ recipe.configure_options << "--with-libiconv-prefix=#{$recipes[:libiconv].path}"
44
+ end
45
+ recipe.cook
46
+ touch checkpoint
47
+ end
48
+ recipe.activate
49
+ end
50
+
51
+ end
52
+
53
+ task :cross do
54
+ host = ENV.fetch("HOST", Rake::ExtensionCompiler.mingw_host)
55
+ $recipes.each do |_, recipe|
56
+ recipe.host = host
57
+ end
58
+ end
59
+
@@ -0,0 +1,77 @@
1
+ $:.unshift File.expand_path('../../../lib',__FILE__)
2
+ require 'rubygems'
3
+ require 'bench_press'
4
+ require 'tiny_tds'
5
+ require 'odbc'
6
+ require 'odbc_utf8'
7
+
8
+ extend BenchPress
9
+
10
+ author 'Ken Collins'
11
+ summary 'Query everything.'
12
+
13
+ reps 1_000
14
+
15
+ @odbc = ODBC.connect ENV['TINYTDS_UNIT_DATASERVER'], 'tinytds', ''
16
+ @odbc.use_time = true
17
+
18
+ @odbc_utf8 = ODBC_UTF8.connect ENV['TINYTDS_UNIT_DATASERVER'], 'tinytds', ''
19
+ @odbc_utf8.use_time = true
20
+
21
+ @tinytds = TinyTds::Client.new(
22
+ :dataserver => ENV['TINYTDS_UNIT_DATASERVER'],
23
+ :username => 'tinytds',
24
+ :password => '',
25
+ :database => 'tinytdstest',
26
+ :appname => 'TinyTds Dev',
27
+ :login_timeout => 5,
28
+ :timeout => 5 )
29
+
30
+ @query_all = "SELECT * FROM [datatypes]"
31
+
32
+
33
+ measure "ODBC (ascii-8bit)" do
34
+ h = @odbc.run(@query_all)
35
+ h.fetch_all
36
+ h.drop
37
+ end
38
+
39
+ # measure "ODBC (utf8)" do
40
+ # h = @odbc_utf8.run(@query_all)
41
+ # h.fetch_all
42
+ # h.drop
43
+ # end
44
+
45
+ measure "TinyTDS (row caching)" do
46
+ @tinytds.execute(@query_all).each
47
+ end
48
+
49
+ measure "TinyTDS (no caching)" do
50
+ @tinytds.execute(@query_all).each(:cache_rows => false)
51
+ end
52
+
53
+
54
+
55
+ =begin
56
+
57
+ Author: Ken Collins
58
+ Date: January 22, 2011
59
+ Summary: Query everything.
60
+
61
+ System Information
62
+ ------------------
63
+ Operating System: Mac OS X 10.6.6 (10J567)
64
+ CPU: Intel Core 2 Duo 1.6 GHz
65
+ Processor Count: 2
66
+ Memory: 4 GB
67
+ ruby 1.8.7 (2010-04-19 patchlevel 253) [i686-darwin10.4.3], MBARI 0x6770, Ruby Enterprise Edition 2010.02
68
+
69
+ "TinyTDS (row caching)" is up to 79% faster over 1,000 repetitions
70
+ ------------------------------------------------------------------
71
+
72
+ TinyTDS (row caching) 4.90862512588501 secs Fastest
73
+ TinyTDS (no caching) 4.91626906394958 secs 0% Slower
74
+ ODBC (ascii-8bit) 23.959536075592 secs 79% Slower
75
+
76
+ =end
77
+
@@ -0,0 +1,106 @@
1
+ require 'rubygems'
2
+ require 'bench_press'
3
+ begin gem 'odbc', '0.99992' ; rescue Gem::LoadError ; end
4
+ require 'odbc'
5
+
6
+ extend BenchPress
7
+
8
+ author 'Ken Collins'
9
+ summary 'Benchmarking ODBC Querys'
10
+
11
+ reps 1_000
12
+
13
+ @client = ODBC.connect ENV['TINYTDS_UNIT_DATASERVER'], 'tinytds', ''
14
+ @client.use_time = true
15
+
16
+ @query_nothing = "SELECT NULL AS [null]"
17
+ @query_ints = "SELECT [int], [bigint], [smallint], [tinyint] FROM [datatypes]"
18
+ @query_binaries = "SELECT [binary_50], [image], [varbinary_50] FROM [datatypes]"
19
+ @query_bits = "SELECT [bit] FROM [datatypes]"
20
+ @query_chars = "SELECT [char_10], [nchar_10], [ntext], [nvarchar_50], [text], [varchar_50] FROM [datatypes]"
21
+ @query_dates = "SELECT [datetime], [smalldatetime] FROM [datatypes]"
22
+ @query_decimals = "SELECT [decimal_9_2], [decimal_16_4], [numeric_18_0], [numeric_36_2] FROM [datatypes]"
23
+ @query_floats = "SELECT [float], [real] FROM [datatypes]"
24
+ @query_moneys = "SELECT [money], [smallmoney] FROM [datatypes]"
25
+ @query_guids = "SELECT [uniqueidentifier] FROM [datatypes]"
26
+ @query_all = "SELECT * FROM [datatypes]"
27
+
28
+ def select_all(query)
29
+ h = @client.run(query)
30
+ h.fetch_all
31
+ h.drop
32
+ end
33
+
34
+
35
+ measure "Nothing" do
36
+ select_all @query_nothing
37
+ end
38
+
39
+ measure "Integers" do
40
+ select_all @query_ints
41
+ end
42
+
43
+ measure "Binaries" do
44
+ select_all @query_binaries
45
+ end
46
+
47
+ measure "Bits" do
48
+ select_all @query_bits
49
+ end
50
+
51
+ measure "Chars" do
52
+ select_all @query_chars
53
+ end
54
+
55
+ measure "Dates" do
56
+ select_all @query_dates
57
+ end
58
+
59
+ measure "Decimals" do
60
+ select_all @query_decimals
61
+ end
62
+
63
+ measure "Floats" do
64
+ select_all @query_floats
65
+ end
66
+
67
+ measure "Moneys" do
68
+ select_all @query_moneys
69
+ end
70
+
71
+ measure "Guids" do
72
+ select_all @query_guids
73
+ end
74
+
75
+ measure "All" do
76
+ select_all @query_all
77
+ end
78
+
79
+
80
+ =begin
81
+
82
+ System Information
83
+ ------------------
84
+ Operating System: Mac OS X 10.6.4 (10F569)
85
+ CPU: Intel Core 2 Duo 2.4 GHz
86
+ Processor Count: 2
87
+ Memory: 4 GB
88
+ ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10.4.0]
89
+
90
+ "Nothing" is up to 98% faster over 1,000 repetitions
91
+ ----------------------------------------------------
92
+
93
+ Nothing 0.297961950302124 secs Fastest
94
+ Bits 0.377611875534058 secs 21% Slower
95
+ Guids 0.381000995635986 secs 21% Slower
96
+ Moneys 0.405518054962158 secs 26% Slower
97
+ Floats 0.409428119659424 secs 27% Slower
98
+ Integers 0.448167085647583 secs 33% Slower
99
+ Decimals 0.471596956253052 secs 36% Slower
100
+ Dates 0.52501106262207 secs 43% Slower
101
+ Binaries 3.66349482536316 secs 91% Slower
102
+ Chars 6.82928085327148 secs 95% Slower
103
+ All 28.4982612133026 secs 98% Slower
104
+
105
+ =end
106
+