tiny_tds 0.4.3 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+