diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc45f0f6..f209ad03 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -573,3 +573,18 @@ jobs: shell: bash run: | ruby -e "require 'tiny_tds'; puts TinyTds::Gem.root_path" + + standardrb: + name: standardrb + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "2.7" + bundler-cache: true + + - name: Check standardrb + shell: bash + run: bundle exec standardrb diff --git a/Gemfile b/Gemfile index 851fabc2..3be9c3cd 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,2 @@ -source 'https://rubygems.org' +source "https://rubygems.org" gemspec diff --git a/README.md b/README.md index ce97af80..718a14b4 100644 --- a/README.md +++ b/README.md @@ -439,6 +439,10 @@ $ rake TINYTDS_UNIT_DATASERVER=mydbserver TINYTDS_SCHEMA=sqlserver_2017 $ rake TINYTDS_UNIT_HOST=mydb.host.net TINYTDS_SCHEMA=sqlserver_azure ``` +### Code formatting + +We are using `standardrb` to format our code. Just run `bundle exec standardrb --fix` to format all Ruby files. + ### Compiling Gems for Windows and Linux > [!WARNING] diff --git a/Rakefile b/Rakefile index 887b9ff2..417372ba 100644 --- a/Rakefile +++ b/Rakefile @@ -1,55 +1,54 @@ -# encoding: UTF-8 -require 'rbconfig' -require 'rake' -require 'rake/clean' -require 'rake/extensiontask' +require "rbconfig" +require "rake" +require "rake/clean" +require "rake/extensiontask" -SPEC = Gem::Specification.load(File.expand_path('../tiny_tds.gemspec', __FILE__)) +SPEC = Gem::Specification.load(File.expand_path("../tiny_tds.gemspec", __FILE__)) CrossLibrary = Struct.new :platform, :openssl_config CrossLibraries = [ - ['x64-mingw-ucrt', 'mingw64'], - ['x64-mingw32', 'mingw64'], - ['x86_64-linux-gnu', 'linux-x86_64'], - ['x86_64-linux-musl', 'linux-x86_64'], - ['aarch64-linux-gnu', 'linux-aarch64'], - ['aarch64-linux-musl', 'linux-aarch64'], + ["x64-mingw-ucrt", "mingw64"], + ["x64-mingw32", "mingw64"], + ["x86_64-linux-gnu", "linux-x86_64"], + ["x86_64-linux-musl", "linux-x86_64"], + ["aarch64-linux-gnu", "linux-aarch64"], + ["aarch64-linux-musl", "linux-aarch64"] ].map do |platform, openssl_config| CrossLibrary.new platform, openssl_config end # Add our project specific files to clean for a rebuild -CLEAN.include FileList["{ext,lib}/**/*.{so,#{RbConfig::CONFIG['DLEXT']},o}"], - FileList["exe/*"] +CLEAN.include FileList["{ext,lib}/**/*.{so,#{RbConfig::CONFIG["DLEXT"]},o}"], + FileList["exe/*"] # Clobber all our temp files and ports files including .install files # and archives CLOBBER.include FileList["tmp/**/*"], - FileList["ports/**/*"].exclude(%r{^ports/archives}) + FileList["ports/**/*"].exclude(%r{^ports/archives}) -Dir['tasks/*.rake'].sort.each { |f| load f } +Dir["tasks/*.rake"].sort.each { |f| load f } -Rake::ExtensionTask.new('tiny_tds', SPEC) do |ext| - ext.lib_dir = 'lib/tiny_tds' +Rake::ExtensionTask.new("tiny_tds", SPEC) do |ext| + ext.lib_dir = "lib/tiny_tds" ext.cross_compile = true ext.cross_platform = CrossLibraries.map(&:platform) # Add dependent DLLs to the cross gems ext.cross_compiling do |spec| # The fat binary gem doesn't depend on the freetds package, since it bundles the library. - spec.metadata.delete('msys2_mingw_dependencies') - - if spec.platform.to_s =~ /mingw/ + spec.metadata.delete("msys2_mingw_dependencies") + + if /mingw/.match?(spec.platform.to_s) spec.files += [ - "ports/#{spec.platform.to_s}/bin/libsybdb-5.dll", - "ports/#{spec.platform.to_s}/bin/defncopy.exe", - "ports/#{spec.platform.to_s}/bin/tsql.exe" + "ports/#{spec.platform}/bin/libsybdb-5.dll", + "ports/#{spec.platform}/bin/defncopy.exe", + "ports/#{spec.platform}/bin/tsql.exe" ] - elsif spec.platform.to_s =~ /linux/ + elsif /linux/.match?(spec.platform.to_s) spec.files += [ - "ports/#{spec.platform.to_s}/lib/libsybdb.so.5", - "ports/#{spec.platform.to_s}/bin/defncopy", - "ports/#{spec.platform.to_s}/bin/tsql" + "ports/#{spec.platform}/lib/libsybdb.so.5", + "ports/#{spec.platform}/bin/defncopy", + "ports/#{spec.platform}/bin/tsql" ] end end diff --git a/ext/tiny_tds/extconf.rb b/ext/tiny_tds/extconf.rb index 55a0d65e..ec155c14 100644 --- a/ext/tiny_tds/extconf.rb +++ b/ext/tiny_tds/extconf.rb @@ -1,19 +1,19 @@ -require 'mkmf' -require_relative 'extconsts' - -if ENV['MAINTAINER_MODE'] - $stderr.puts "Maintainer mode enabled." - $CFLAGS << - ' -Wall' << - ' -ggdb' << - ' -DDEBUG' << - ' -pedantic' - $LDFLAGS << - ' -ggdb' +require "mkmf" +require_relative "extconsts" + +if ENV["MAINTAINER_MODE"] + warn "Maintainer mode enabled." + $CFLAGS << # standard:disable Style/GlobalVars + " -Wall" \ + " -ggdb" \ + " -DDEBUG" \ + " -pedantic" + $LDFLAGS << # standard:disable Style/GlobalVars + " -ggdb" end -if gem_platform=with_config("cross-build") - require 'mini_portile2' +if (gem_platform = with_config("cross-build")) + require "mini_portile2" openssl_platform = with_config("openssl-platform") @@ -23,7 +23,7 @@ class BuildRecipe < MiniPortile def initialize(name, version, files) super(name, version) self.files = files - rootdir = File.expand_path('../../..', __FILE__) + rootdir = File.expand_path("../../..", __FILE__) self.target = File.join(rootdir, "ports") self.patch_files = Dir[File.join("patches", self.name, self.version, "*.patch")].sort end @@ -34,35 +34,35 @@ def port_path end def cook_and_activate - checkpoint = File.join(self.target, "#{self.name}-#{self.version}-#{gem_platform}.installed") - + checkpoint = File.join(target, "#{name}-#{version}-#{gem_platform}.installed") + unless File.exist?(checkpoint) - self.cook - FileUtils.touch checkpoint - end - - self.activate + cook + FileUtils.touch checkpoint + end + + activate self end end openssl_recipe = BuildRecipe.new("openssl", OPENSSL_VERSION, [OPENSSL_SOURCE_URI]).tap do |recipe| - class << recipe + class << recipe attr_accessor :openssl_platform - + def configure envs = [] envs << "CFLAGS=-DDSO_WIN32 -DOPENSSL_THREADS" if MiniPortile.windows? envs << "CFLAGS=-fPIC -DOPENSSL_THREADS" if MiniPortile.linux? - execute('configure', ['env', *envs, "./Configure", openssl_platform, "threads", "-static", "CROSS_COMPILE=#{host}-", configure_prefix, "--libdir=lib"], altlog: "config.log") + execute("configure", ["env", *envs, "./Configure", openssl_platform, "threads", "-static", "CROSS_COMPILE=#{host}-", configure_prefix, "--libdir=lib"], altlog: "config.log") end - + def compile - execute('compile', "#{make_cmd} build_libs") + execute("compile", "#{make_cmd} build_libs") end - + def install - execute('install', "#{make_cmd} install_dev") + execute("install", "#{make_cmd} install_dev") end end @@ -122,30 +122,30 @@ def configure_defaults end # enable relative path to later load the FreeTDS shared library - $LDFLAGS << " '-Wl,-rpath=$$ORIGIN/../../../ports/#{gem_platform}/lib'" + $LDFLAGS << " '-Wl,-rpath=$$ORIGIN/../../../ports/#{gem_platform}/lib'" # standard:disable Style/GlobalVars - dir_config('freetds', "#{freetds_recipe.path}/include", "#{freetds_recipe.path}/lib") + dir_config("freetds", "#{freetds_recipe.path}/include", "#{freetds_recipe.path}/lib") else # Make sure to check the ports path for the configured host - architecture = RbConfig::CONFIG['arch'] + architecture = RbConfig::CONFIG["arch"] project_dir = File.expand_path("../../..", __FILE__) - freetds_ports_dir = File.join(project_dir, 'ports', architecture, 'freetds', FREETDS_VERSION) + freetds_ports_dir = File.join(project_dir, "ports", architecture, "freetds", FREETDS_VERSION) freetds_ports_dir = File.expand_path(freetds_ports_dir) - + # Add all the special path searching from the original tiny_tds build # order is important here! First in, first searched. - DIRS = %w( + DIRS = %w[ /opt/local /usr/local - ) + ] - if RbConfig::CONFIG['host_os'] =~ /darwin/i + if /darwin/i.match?(RbConfig::CONFIG["host_os"]) # Ruby below 2.7 seems to label the host CPU on Apple Silicon as aarch64 # 2.7 and above print is as ARM64 - target_host_cpu = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7') ? 'aarch64' : 'arm64' + target_host_cpu = (Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7")) ? "aarch64" : "arm64" - if RbConfig::CONFIG['host_cpu'] == target_host_cpu + if RbConfig::CONFIG["host_cpu"] == target_host_cpu # Homebrew on Apple Silicon installs into /opt/hombrew # https://docs.brew.sh/Installation # On Intel Macs, it is /usr/local, so no changes necessary to DIRS @@ -162,7 +162,7 @@ def configure_defaults # Grab freetds environment variable for use by people on services like # Heroku who they can't easily use bundler config to set directories - DIRS.unshift(ENV['FREETDS_DIR']) if ENV.has_key?('FREETDS_DIR') + DIRS.unshift(ENV["FREETDS_DIR"]) if ENV.has_key?("FREETDS_DIR") # Add the search paths for freetds configured above ldirs = DIRS.flat_map do |path| @@ -175,15 +175,15 @@ def configure_defaults [idir, "#{idir}/freetds"] end - puts "looking for freetds headers in the following directories:\n#{idirs.map{|a| " - #{a}\n"}.join}" - puts "looking for freetds library in the following directories:\n#{ldirs.map{|a| " - #{a}\n"}.join}" - dir_config('freetds', idirs, ldirs) + puts "looking for freetds headers in the following directories:\n#{idirs.map { |a| " - #{a}\n" }.join}" + puts "looking for freetds library in the following directories:\n#{ldirs.map { |a| " - #{a}\n" }.join}" + dir_config("freetds", idirs, ldirs) end -find_header('sybfront.h') or abort "Can't find the 'sybfront.h' header" -find_header('sybdb.h') or abort "Can't find the 'sybdb.h' header" +find_header("sybfront.h") or abort "Can't find the 'sybfront.h' header" +find_header("sybdb.h") or abort "Can't find the 'sybdb.h' header" -unless have_library('sybdb', 'dbanydatecrack') +unless have_library("sybdb", "dbanydatecrack") abort "Failed! Do you have FreeTDS 1.0.0 or higher installed?" end diff --git a/ext/tiny_tds/extconsts.rb b/ext/tiny_tds/extconsts.rb index 64af1704..6151aaf5 100644 --- a/ext/tiny_tds/extconsts.rb +++ b/ext/tiny_tds/extconsts.rb @@ -1,9 +1,8 @@ - -ICONV_VERSION = ENV['TINYTDS_ICONV_VERSION'] || "1.17" +ICONV_VERSION = ENV["TINYTDS_ICONV_VERSION"] || "1.17" ICONV_SOURCE_URI = "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-#{ICONV_VERSION}.tar.gz" -OPENSSL_VERSION = ENV['TINYTDS_OPENSSL_VERSION'] || '3.4.0' +OPENSSL_VERSION = ENV["TINYTDS_OPENSSL_VERSION"] || "3.4.0" OPENSSL_SOURCE_URI = "https://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz" -FREETDS_VERSION = ENV['TINYTDS_FREETDS_VERSION'] || '1.4.23' +FREETDS_VERSION = ENV["TINYTDS_FREETDS_VERSION"] || "1.4.23" FREETDS_SOURCE_URI = "http://www.freetds.org/files/stable/freetds-#{FREETDS_VERSION}.tar.bz2" diff --git a/lib/tiny_tds.rb b/lib/tiny_tds.rb index 11125a2c..e00c7373 100644 --- a/lib/tiny_tds.rb +++ b/lib/tiny_tds.rb @@ -1,31 +1,28 @@ -# encoding: UTF-8 -require 'date' -require 'bigdecimal' -require 'rational' +require "date" +require "bigdecimal" -require 'tiny_tds/version' -require 'tiny_tds/error' -require 'tiny_tds/client' -require 'tiny_tds/result' -require 'tiny_tds/gem' +require "tiny_tds/version" +require "tiny_tds/error" +require "tiny_tds/client" +require "tiny_tds/result" +require "tiny_tds/gem" module TinyTds - # Is this file part of a fat binary gem with bundled freetds? # This path must be enabled by add_dll_directory on Windows. gplat = ::Gem::Platform.local FREETDS_LIB_PATH = Dir[File.expand_path("../ports/#{gplat.cpu}-#{gplat.os}*/lib", __dir__)].first add_dll_path = proc do |path, &block| - if RUBY_PLATFORM =~/(mswin|mingw)/i && path + if RUBY_PLATFORM =~ /(mswin|mingw)/i && path begin - require 'ruby_installer/runtime' + require "ruby_installer/runtime" RubyInstaller::Runtime.add_dll_directory(path, &block) rescue LoadError - old_path = ENV['PATH'] - ENV['PATH'] = "#{path};#{old_path}" + old_path = ENV["PATH"] + ENV["PATH"] = "#{path};#{old_path}" block.call - ENV['PATH'] = old_path + ENV["PATH"] = old_path end else # libsybdb is found by a relative rpath in the cross compiled extension dll @@ -35,13 +32,11 @@ module TinyTds end add_dll_path.call(FREETDS_LIB_PATH) do - begin - # Try the . subdirectory for fat binary gems - major_minor = RUBY_VERSION[ /^(\d+\.\d+)/ ] or - raise "Oops, can't extract the major/minor version from #{RUBY_VERSION.dump}" - require "tiny_tds/#{major_minor}/tiny_tds" - rescue LoadError - require 'tiny_tds/tiny_tds' - end + # Try the . subdirectory for fat binary gems + major_minor = RUBY_VERSION[/^(\d+\.\d+)/] or + raise "Oops, can't extract the major/minor version from #{RUBY_VERSION.dump}" + require "tiny_tds/#{major_minor}/tiny_tds" + rescue LoadError + require "tiny_tds/tiny_tds" end end diff --git a/lib/tiny_tds/bin.rb b/lib/tiny_tds/bin.rb index 87cee11a..e36fe37d 100644 --- a/lib/tiny_tds/bin.rb +++ b/lib/tiny_tds/bin.rb @@ -1,23 +1,22 @@ -require_relative './version' -require_relative './gem' -require 'shellwords' +require_relative "version" +require_relative "gem" +require "shellwords" module TinyTds class Bin - attr_reader :name class << self def exe(name, *args) bin = new(name) - puts bin.info unless args.any? { |x| x == '-q' } + puts bin.info unless args.any? { |x| x == "-q" } bin.run(*args) end end def initialize(name) @root = Gem.root_path - @exts = (ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']) | ['.exe'] + @exts = (ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]) | [".exe"] @name = name @binstub = find_bin @@ -33,7 +32,7 @@ def run(*args) end def path - @path ||= @exefile && File.exist?(@exefile) ? @exefile : which + @path ||= (@exefile && File.exist?(@exefile)) ? @exefile : which end def info @@ -43,26 +42,26 @@ def info private def search_paths - ENV['PATH'].split File::PATH_SEPARATOR + ENV["PATH"].split File::PATH_SEPARATOR end def with_ports_paths - old_path = ENV['PATH'] + old_path = ENV["PATH"] begin - ENV['PATH'] = [ + ENV["PATH"] = [ Gem.ports_bin_paths, old_path ].flatten.join File::PATH_SEPARATOR yield if block_given? ensure - ENV['PATH'] = old_path + ENV["PATH"] = old_path end end def find_bin - File.join @root, 'bin', name + File.join @root, "bin", name end def find_exe diff --git a/lib/tiny_tds/client.rb b/lib/tiny_tds/client.rb index 5565a164..92a195b7 100644 --- a/lib/tiny_tds/client.rb +++ b/lib/tiny_tds/client.rb @@ -1,6 +1,5 @@ module TinyTds class Client - @default_query_options = { as: :hash, symbolize_keys: false, @@ -13,7 +12,6 @@ class Client attr_reader :message_handler class << self - attr_reader :default_query_options # Most, if not all, iconv encoding names can be found by ruby. Just in case, you can @@ -27,7 +25,6 @@ def transpose_iconv_encoding(encoding) def local_offset ::Time.local(2010).utc_offset.to_r / 86_400 end - end # rubocop:disable Metrics/AbcSize @@ -36,23 +33,23 @@ def local_offset # rubocop:disable Metrics/PerceivedComplexity def initialize(opts = {}) if opts[:dataserver].to_s.empty? && opts[:host].to_s.empty? - raise ArgumentError, 'missing :host option if no :dataserver given' + raise ArgumentError, "missing :host option if no :dataserver given" end @message_handler = opts[:message_handler] if @message_handler && !@message_handler.respond_to?(:call) - raise ArgumentError, ':message_handler must implement `call` (eg, a Proc or a Method)' + raise ArgumentError, ":message_handler must implement `call` (eg, a Proc or a Method)" end opts[:username] = parse_username(opts) @query_options = self.class.default_query_options.dup - opts[:password] = opts[:password].to_s if opts[:password] && opts[:password].to_s.strip != '' - opts[:appname] ||= 'TinyTds' + opts[:password] = opts[:password].to_s if opts[:password] && opts[:password].to_s.strip != "" + opts[:appname] ||= "TinyTds" opts[:tds_version] = tds_versions_setter(opts) opts[:use_utf16] = opts[:use_utf16].nil? || ["true", "1", "yes"].include?(opts[:use_utf16].to_s) opts[:login_timeout] ||= 60 opts[:timeout] ||= 5 - opts[:encoding] = opts[:encoding].nil? || opts[:encoding].casecmp('utf8').zero? ? 'UTF-8' : opts[:encoding].upcase + opts[:encoding] = (opts[:encoding].nil? || opts[:encoding].casecmp("utf8").zero?) ? "UTF-8" : opts[:encoding].upcase opts[:port] ||= 1433 opts[:dataserver] = "#{opts[:host]}:#{opts[:port]}" if opts[:dataserver].to_s.empty? forced_integer_keys = [:login_timeout, :port, :timeout] @@ -79,14 +76,14 @@ def parse_username(opts) host = opts[:host] username = opts[:username] return username if username.nil? || !opts[:azure] - return username if username.include?('@') && !username.include?('database.windows.net') - user, domain = username.split('@') + return username if username.include?("@") && !username.include?("database.windows.net") + user, domain = username.split("@") domain ||= host - "#{user}@#{domain.split('.').first}" + "#{user}@#{domain.split(".").first}" end def tds_versions_setter(opts = {}) - v = opts[:tds_version] || ENV['TDSVER'] || '7.3' + v = opts[:tds_version] || ENV["TDSVER"] || "7.3" TDS_VERSIONS_SETTERS[v.to_s] end @@ -94,22 +91,22 @@ def tds_versions_setter(opts = {}) # DBVERSION_xxx are used with dbsetversion() # TDS_VERSIONS_SETTERS = { - 'unknown' => 0, - '46' => 1, - '100' => 2, - '42' => 3, - '70' => 4, - '7.0' => 4, - '71' => 5, - '7.1' => 5, - '80' => 5, - '8.0' => 5, - '72' => 6, - '7.2' => 6, - '90' => 6, - '9.0' => 6, - '73' => 7, - '7.3' => 7 + "unknown" => 0, + "46" => 1, + "100" => 2, + "42" => 3, + "70" => 4, + "7.0" => 4, + "71" => 5, + "7.1" => 5, + "80" => 5, + "8.0" => 5, + "72" => 6, + "7.2" => 6, + "90" => 6, + "9.0" => 6, + "73" => 7, + "7.3" => 7 }.freeze # From sybdb.h comments: @@ -117,20 +114,19 @@ def tds_versions_setter(opts = {}) # The integer values of the constants are poorly chosen. # TDS_VERSIONS_GETTERS = { - 0 => { name: 'DBTDS_UNKNOWN', description: 'Unknown' }, - 1 => { name: 'DBTDS_2_0', description: 'Pre 4.0 SQL Server' }, - 2 => { name: 'DBTDS_3_4', description: 'Microsoft SQL Server (3.0)' }, - 3 => { name: 'DBTDS_4_0', description: '4.0 SQL Server' }, - 4 => { name: 'DBTDS_4_2', description: '4.2 SQL Server' }, - 5 => { name: 'DBTDS_4_6', description: '2.0 OpenServer and 4.6 SQL Server.' }, - 6 => { name: 'DBTDS_4_9_5', description: '4.9.5 (NCR) SQL Server' }, - 7 => { name: 'DBTDS_5_0', description: '5.0 SQL Server' }, - 8 => { name: 'DBTDS_7_0', description: 'Microsoft SQL Server 7.0' }, - 9 => { name: 'DBTDS_7_1/DBTDS_8_0', description: 'Microsoft SQL Server 2000' }, - 10 => { name: 'DBTDS_7_2/DBTDS_9_0', description: 'Microsoft SQL Server 2005' }, - 11 => { name: 'DBTDS_7_3', description: 'Microsoft SQL Server 2008' }, - 12 => { name: 'DBTDS_7_4', description: 'Microsoft SQL Server 2012/2014' } + 0 => {name: "DBTDS_UNKNOWN", description: "Unknown"}, + 1 => {name: "DBTDS_2_0", description: "Pre 4.0 SQL Server"}, + 2 => {name: "DBTDS_3_4", description: "Microsoft SQL Server (3.0)"}, + 3 => {name: "DBTDS_4_0", description: "4.0 SQL Server"}, + 4 => {name: "DBTDS_4_2", description: "4.2 SQL Server"}, + 5 => {name: "DBTDS_4_6", description: "2.0 OpenServer and 4.6 SQL Server."}, + 6 => {name: "DBTDS_4_9_5", description: "4.9.5 (NCR) SQL Server"}, + 7 => {name: "DBTDS_5_0", description: "5.0 SQL Server"}, + 8 => {name: "DBTDS_7_0", description: "Microsoft SQL Server 7.0"}, + 9 => {name: "DBTDS_7_1/DBTDS_8_0", description: "Microsoft SQL Server 2000"}, + 10 => {name: "DBTDS_7_2/DBTDS_9_0", description: "Microsoft SQL Server 2005"}, + 11 => {name: "DBTDS_7_3", description: "Microsoft SQL Server 2008"}, + 12 => {name: "DBTDS_7_4", description: "Microsoft SQL Server 2012/2014"} }.freeze - end end diff --git a/lib/tiny_tds/error.rb b/lib/tiny_tds/error.rb index d658ed1e..7a7ade8d 100644 --- a/lib/tiny_tds/error.rb +++ b/lib/tiny_tds/error.rb @@ -1,6 +1,5 @@ module TinyTds class Error < StandardError - attr_accessor :source, :severity, :db_error_number, :os_error_number def initialize(message) @@ -9,6 +8,5 @@ def initialize(message) @db_error_number = nil @os_error_number = nil end - end end diff --git a/lib/tiny_tds/gem.rb b/lib/tiny_tds/gem.rb index 55be78b4..8a9c8ff6 100644 --- a/lib/tiny_tds/gem.rb +++ b/lib/tiny_tds/gem.rb @@ -1,22 +1,22 @@ -require 'rbconfig' +require "rbconfig" module TinyTds module Gem class << self def root_path - File.expand_path '../../..', __FILE__ + File.expand_path "../../..", __FILE__ end def ports_root_path - File.join(root_path,'ports') + File.join(root_path, "ports") end def ports_bin_paths - Dir.glob(File.join(ports_root_path, '**', 'bin')) + Dir.glob(File.join(ports_root_path, "**", "bin")) end def ports_lib_paths - Dir.glob(File.join(ports_root_path, '**', 'lib')) + Dir.glob(File.join(ports_root_path, "**", "lib")) end end end diff --git a/lib/tiny_tds/result.rb b/lib/tiny_tds/result.rb index 618c044b..c0683b90 100644 --- a/lib/tiny_tds/result.rb +++ b/lib/tiny_tds/result.rb @@ -1,7 +1,5 @@ module TinyTds class Result - include Enumerable - end end diff --git a/lib/tiny_tds/version.rb b/lib/tiny_tds/version.rb index 4313ffae..de367fb8 100644 --- a/lib/tiny_tds/version.rb +++ b/lib/tiny_tds/version.rb @@ -1,3 +1,3 @@ module TinyTds - VERSION = File.read(File.expand_path('../../../VERSION', __FILE__)).chomp + VERSION = File.read(File.expand_path("../../../VERSION", __FILE__)).chomp end diff --git a/tasks/native_gem.rake b/tasks/native_gem.rake index 18be796d..2d7d0f00 100644 --- a/tasks/native_gem.rake +++ b/tasks/native_gem.rake @@ -1,16 +1,16 @@ CrossLibraries.each do |xlib| - platform = xlib.platform - - desc "Build fat binary gem for platform #{platform}" - task "gem:native:#{platform}" do - require "rake_compiler_dock" + platform = xlib.platform - RakeCompilerDock.sh <<-EOT, platform: platform + desc "Build fat binary gem for platform #{platform}" + task "gem:native:#{platform}" do + require "rake_compiler_dock" + + RakeCompilerDock.sh <<-EOT, platform: platform bundle install && rake native:#{platform} pkg/#{SPEC.full_name}-#{platform}.gem MAKEOPTS=-j`nproc` RUBY_CC_VERSION=3.4.1:3.3.5:3.2.0:3.1.0:3.0.0:2.7.0 MAKEFLAGS="V=1" - EOT - end + EOT + end - desc "Build the native binary gems" - multitask 'gem:native' => "gem:native:#{platform}" + desc "Build the native binary gems" + multitask "gem:native" => "gem:native:#{platform}" end diff --git a/tasks/package.rake b/tasks/package.rake index 99717d03..d9627886 100644 --- a/tasks/package.rake +++ b/tasks/package.rake @@ -1,8 +1,6 @@ -# encoding: UTF-8 -require 'rubygems/package_task' +require "rubygems/package_task" Gem::PackageTask.new(SPEC) do |pkg| pkg.need_tar = false pkg.need_zip = false end - diff --git a/tasks/ports.rake b/tasks/ports.rake index 4fdc9498..e01a389a 100644 --- a/tasks/ports.rake +++ b/tasks/ports.rake @@ -1,4 +1,4 @@ -require_relative '../ext/tiny_tds/extconsts' +require_relative "../ext/tiny_tds/extconsts" namespace :ports do libraries_to_compile = { @@ -19,8 +19,6 @@ namespace :ports do ports_version[:platform] = args.gem_platform - File.open(".ports_versions", "w") do |f| - f.write ports_version - end + File.write(".ports_versions", ports_version) end end diff --git a/tasks/test.rake b/tasks/test.rake index 10ecac47..f83f3a78 100644 --- a/tasks/test.rake +++ b/tasks/test.rake @@ -1,9 +1,7 @@ -# encoding: UTF-8 -require 'rake/testtask' +require "rake/testtask" Rake::TestTask.new do |t| - t.libs << 'test' - t.test_files = FileList['test/**/*_test.rb'] + t.libs << "test" + t.test_files = FileList["test/**/*_test.rb"] t.verbose = true end - diff --git a/test/benchmark/query.rb b/test/benchmark/query.rb deleted file mode 100644 index 923f0076..00000000 --- a/test/benchmark/query.rb +++ /dev/null @@ -1,77 +0,0 @@ -$:.unshift File.expand_path('../../../lib',__FILE__) -require 'rubygems' -require 'bench_press' -require 'tiny_tds' -require 'odbc' -require 'odbc_utf8' - -extend BenchPress - -author 'Ken Collins' -summary 'Query everything.' - -reps 1_000 - -@odbc = ODBC.connect ENV['TINYTDS_UNIT_DATASERVER'], 'tinytds', '' -@odbc.use_time = true - -@odbc_utf8 = ODBC_UTF8.connect ENV['TINYTDS_UNIT_DATASERVER'], 'tinytds', '' -@odbc_utf8.use_time = true - -@tinytds = TinyTds::Client.new( - :dataserver => ENV['TINYTDS_UNIT_DATASERVER'], - :username => 'tinytds', - :password => '', - :database => 'tinytdstest', - :appname => 'TinyTds Dev', - :login_timeout => 5, - :timeout => 5 ) - -@query_all = "SELECT * FROM [datatypes]" - - -measure "ODBC (ascii-8bit)" do - h = @odbc.run(@query_all) - h.fetch_all - h.drop -end - -# measure "ODBC (utf8)" do -# h = @odbc_utf8.run(@query_all) -# h.fetch_all -# h.drop -# end - -measure "TinyTDS (row caching)" do - @tinytds.execute(@query_all).each -end - -measure "TinyTDS (no caching)" do - @tinytds.execute(@query_all).each(:cache_rows => false) -end - - - -=begin - -Author: Ken Collins -Date: January 22, 2011 -Summary: Query everything. - -System Information ------------------- - Operating System: Mac OS X 10.6.6 (10J567) - CPU: Intel Core 2 Duo 1.6 GHz - Processor Count: 2 - Memory: 4 GB - ruby 1.8.7 (2010-04-19 patchlevel 253) [i686-darwin10.4.3], MBARI 0x6770, Ruby Enterprise Edition 2010.02 - -"TinyTDS (row caching)" is up to 79% faster over 1,000 repetitions ------------------------------------------------------------------- - - TinyTDS (row caching) 4.90862512588501 secs Fastest - TinyTDS (no caching) 4.91626906394958 secs 0% Slower - ODBC (ascii-8bit) 23.959536075592 secs 79% Slower - -=end - diff --git a/test/benchmark/query_odbc.rb b/test/benchmark/query_odbc.rb deleted file mode 100644 index 488d715b..00000000 --- a/test/benchmark/query_odbc.rb +++ /dev/null @@ -1,106 +0,0 @@ -require 'rubygems' -require 'bench_press' -begin gem 'odbc', '0.99992' ; rescue Gem::LoadError ; end -require 'odbc' - -extend BenchPress - -author 'Ken Collins' -summary 'Benchmarking ODBC Querys' - -reps 1_000 - -@client = ODBC.connect ENV['TINYTDS_UNIT_DATASERVER'], 'tinytds', '' -@client.use_time = true - -@query_nothing = "SELECT NULL AS [null]" -@query_ints = "SELECT [int], [bigint], [smallint], [tinyint] FROM [datatypes]" -@query_binaries = "SELECT [binary_50], [image], [varbinary_50] FROM [datatypes]" -@query_bits = "SELECT [bit] FROM [datatypes]" -@query_chars = "SELECT [char_10], [nchar_10], [ntext], [nvarchar_50], [text], [varchar_50] FROM [datatypes]" -@query_dates = "SELECT [datetime], [smalldatetime] FROM [datatypes]" -@query_decimals = "SELECT [decimal_9_2], [decimal_16_4], [numeric_18_0], [numeric_36_2] FROM [datatypes]" -@query_floats = "SELECT [float], [real] FROM [datatypes]" -@query_moneys = "SELECT [money], [smallmoney] FROM [datatypes]" -@query_guids = "SELECT [uniqueidentifier] FROM [datatypes]" -@query_all = "SELECT * FROM [datatypes]" - -def select_all(query) - h = @client.run(query) - h.fetch_all - h.drop -end - - -measure "Nothing" do - select_all @query_nothing -end - -measure "Integers" do - select_all @query_ints -end - -measure "Binaries" do - select_all @query_binaries -end - -measure "Bits" do - select_all @query_bits -end - -measure "Chars" do - select_all @query_chars -end - -measure "Dates" do - select_all @query_dates -end - -measure "Decimals" do - select_all @query_decimals -end - -measure "Floats" do - select_all @query_floats -end - -measure "Moneys" do - select_all @query_moneys -end - -measure "Guids" do - select_all @query_guids -end - -measure "All" do - select_all @query_all -end - - -=begin - -System Information ------------------- - Operating System: Mac OS X 10.6.4 (10F569) - CPU: Intel Core 2 Duo 2.4 GHz - Processor Count: 2 - Memory: 4 GB - ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10.4.0] - -"Nothing" is up to 98% faster over 1,000 repetitions ----------------------------------------------------- - - Nothing 0.297961950302124 secs Fastest - Bits 0.377611875534058 secs 21% Slower - Guids 0.381000995635986 secs 21% Slower - Moneys 0.405518054962158 secs 26% Slower - Floats 0.409428119659424 secs 27% Slower - Integers 0.448167085647583 secs 33% Slower - Decimals 0.471596956253052 secs 36% Slower - Dates 0.52501106262207 secs 43% Slower - Binaries 3.66349482536316 secs 91% Slower - Chars 6.82928085327148 secs 95% Slower - All 28.4982612133026 secs 98% Slower - -=end - diff --git a/test/benchmark/query_tinytds.rb b/test/benchmark/query_tinytds.rb deleted file mode 100644 index 971b74a0..00000000 --- a/test/benchmark/query_tinytds.rb +++ /dev/null @@ -1,126 +0,0 @@ -require 'rubygems' -require 'bench_press' -$:.unshift File.expand_path('../../../lib',__FILE__) -require 'tiny_tds' - -extend BenchPress - -author 'Ken Collins' -summary 'Benchmark TinyTds Querys' - -reps 1_000 - -@client = TinyTds::Client.new({ - :dataserver => ENV['TINYTDS_UNIT_DATASERVER'], - :username => 'tinytds', - :password => '', - :database => 'tinytdstest', - :appname => 'TinyTds Dev', - :login_timeout => 5, - :timeout => 5 -}) - -@query_nothing = "SELECT NULL AS [null]" -@query_ints = "SELECT [int], [bigint], [smallint], [tinyint] FROM [datatypes]" -@query_binaries = "SELECT [binary_50], [image], [varbinary_50] FROM [datatypes]" -@query_bits = "SELECT [bit] FROM [datatypes]" -@query_chars = "SELECT [char_10], [nchar_10], [ntext], [nvarchar_50], [text], [varchar_50] FROM [datatypes]" -@query_dates = "SELECT [datetime], [smalldatetime] FROM [datatypes]" -@query_decimals = "SELECT [decimal_9_2], [decimal_16_4], [numeric_18_0], [numeric_36_2] FROM [datatypes]" -@query_floats = "SELECT [float], [real] FROM [datatypes]" -@query_moneys = "SELECT [money], [smallmoney] FROM [datatypes]" -@query_guids = "SELECT [uniqueidentifier] FROM [datatypes]" -@query_all = "SELECT * FROM [datatypes]" - -def select_all(query) - @client.execute(query).each -end - - -measure "Nothing" do - select_all @query_nothing -end - -measure "Integers" do - select_all @query_ints -end - -measure "Binaries" do - select_all @query_binaries -end - -measure "Bits" do - select_all @query_bits -end - -measure "Chars" do - select_all @query_chars -end - -measure "Dates" do - select_all @query_dates -end - -measure "Decimals" do - select_all @query_decimals -end - -measure "Floats" do - select_all @query_floats -end - -measure "Moneys" do - select_all @query_moneys -end - -measure "Guids" do - select_all @query_guids -end - -measure "All" do - select_all @query_all -end - - -=begin - -Query Tinytds -============= -Author: Ken Collins -Date: September 11, 2011 -Summary: Benchmark TinyTds Querys - -System Information ------------------- - Operating System: Mac OS X 10.7.1 (11B26) - CPU: Quad-Core Intel Xeon 2.66 GHz - Processor Count: 4 - Memory: 24 GB - ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-darwin11.1.0], MBARI 0x6770, Ruby Enterprise Edition 2011.03 - ----------------------------------------------------- - (before 64bit times) (after 64bit times) - Nothing 0.287657022476196 secs Nothing 0.289273977279663 secs - Bits 0.406533002853394 secs Bits 0.424988031387329 secs - Guids 0.419962882995605 secs Guids 0.427381992340088 secs - Floats 0.452103137969971 secs Floats 0.455377101898193 secs - Moneys 0.481696844100952 secs Moneys 0.485175132751465 secs - Integers 0.496185064315796 secs Integers 0.525003910064697 secs - Binaries 0.538873195648193 secs Decimals 0.541536808013916 secs - Decimals 0.540570974349976 secs Binaries 0.542865991592407 secs - Dates 0.761389970779419 secs Dates 1.51440119743347 secs - Chars 0.793163061141968 secs Chars 0.666505098342896 secs - All 4.4630811214447 secs All 5.17242312431335 secs - -=end - - - - - - - - - - - diff --git a/test/client_test.rb b/test/client_test.rb index fff406f6..4662f9c7 100644 --- a/test/client_test.rb +++ b/test/client_test.rb @@ -1,124 +1,123 @@ -# encoding: utf-8 -require 'test_helper' +require "test_helper" class ClientTest < TinyTds::TestCase - describe 'with valid credentials' do + describe "with valid credentials" do before do @client = new_connection end - it 'must not be closed' do + it "must not be closed" do assert !@client.closed? assert @client.active? end - it 'allows client connection to be closed' do + it "allows client connection to be closed" do assert @client.close assert @client.closed? assert !@client.active? assert @client.dead? - action = lambda { @client.execute('SELECT 1 as [one]').each } + action = lambda { @client.execute("SELECT 1 as [one]").each } assert_raise_tinytds_error(action) do |e| - assert_match %r{closed connection}i, e.message, 'ignore if non-english test run' + assert_match %r{closed connection}i, e.message, "ignore if non-english test run" end end - it 'has getters for the tds version information (brittle since conf takes precedence)' do + it "has getters for the tds version information (brittle since conf takes precedence)" do if @client.tds_73? assert_equal 11, @client.tds_version - assert_equal 'DBTDS_7_3 - Microsoft SQL Server 2008', @client.tds_version_info + assert_equal "DBTDS_7_3 - Microsoft SQL Server 2008", @client.tds_version_info else assert_equal 9, @client.tds_version - assert_equal 'DBTDS_7_1/DBTDS_8_0 - Microsoft SQL Server 2000', @client.tds_version_info + assert_equal "DBTDS_7_1/DBTDS_8_0 - Microsoft SQL Server 2000", @client.tds_version_info end end - it 'uses UTF-8 client charset/encoding by default' do - assert_equal 'UTF-8', @client.charset - assert_equal Encoding.find('UTF-8'), @client.encoding + it "uses UTF-8 client charset/encoding by default" do + assert_equal "UTF-8", @client.charset + assert_equal Encoding.find("UTF-8"), @client.encoding end - it 'has a #escape method used for quote strings' do + it "has a #escape method used for quote strings" do assert_equal "''hello''", @client.escape("'hello'") end - ['CP850', 'CP1252', 'ISO-8859-1'].each do |encoding| + ["CP850", "CP1252", "ISO-8859-1"].each do |encoding| it "allows valid iconv character set - #{encoding}" do + client = new_connection(encoding: encoding) + assert_equal encoding, client.charset + assert_equal Encoding.find(encoding), client.encoding + ensure + client&.close + end + end + + unless sqlserver_azure? + it "must be able to use :host/:port connection" do + host = ENV["TINYTDS_UNIT_HOST_TEST"] || ENV["TINYTDS_UNIT_HOST"] || "localhost" + port = ENV["TINYTDS_UNIT_PORT_TEST"] || ENV["TINYTDS_UNIT_PORT"] || 1433 begin - client = new_connection(:encoding => encoding) - assert_equal encoding, client.charset - assert_equal Encoding.find(encoding), client.encoding + client = new_connection dataserver: nil, host: host, port: port ensure - client.close if client + client&.close end end end - - it 'must be able to use :host/:port connection' do - host = ENV['TINYTDS_UNIT_HOST_TEST'] || ENV['TINYTDS_UNIT_HOST'] || 'localhost' - port = ENV['TINYTDS_UNIT_PORT_TEST'] || ENV['TINYTDS_UNIT_PORT'] || 1433 - begin - client = new_connection dataserver: nil, host: host, port: port - ensure - client.close if client - end - end unless sqlserver_azure? end - describe 'With in-valid options' do + describe "With in-valid options" do before(:all) do init_toxiproxy end - it 'raises an argument error when no :host given and :dataserver is blank' do - assert_raises(ArgumentError) { new_connection :dataserver => nil, :host => nil } + it "raises an argument error when no :host given and :dataserver is blank" do + assert_raises(ArgumentError) { new_connection dataserver: nil, host: nil } end - it 'raises an argument error when no :username is supplied' do - assert_raises(ArgumentError) { TinyTds::Client.new :username => nil } + it "raises an argument error when no :username is supplied" do + assert_raises(ArgumentError) { TinyTds::Client.new username: nil } end - it 'raises TinyTds exception with undefined :dataserver' do - options = connection_options :login_timeout => 1, :dataserver => 'DOESNOTEXIST' + it "raises TinyTds exception with undefined :dataserver" do + options = connection_options login_timeout: 1, dataserver: "DOESNOTEXIST" action = lambda { new_connection(options) } assert_raise_tinytds_error(action) do |e| # Not sure why tese are different. if ruby_darwin? assert_equal 20009, e.db_error_number assert_equal 9, e.severity - assert_match %r{is unavailable or does not exist}i, e.message, 'ignore if non-english test run' + assert_match %r{is unavailable or does not exist}i, e.message, "ignore if non-english test run" else assert_equal 20012, e.db_error_number assert_equal 2, e.severity - assert_match %r{server name not found in configuration files}i, e.message, 'ignore if non-english test run' + assert_match %r{server name not found in configuration files}i, e.message, "ignore if non-english test run" end end assert_new_connections_work end - it 'raises TinyTds exception with long query past :timeout option' do - client = new_connection :timeout => 1 + it "raises TinyTds exception with long query past :timeout option" do + client = new_connection timeout: 1 action = lambda { client.execute("WaitFor Delay '00:00:02'").do } assert_raise_tinytds_error(action) do |e| assert_equal 20003, e.db_error_number assert_equal 6, e.severity - assert_match %r{timed out}i, e.message, 'ignore if non-english test run' + assert_match %r{timed out}i, e.message, "ignore if non-english test run" end assert_client_works(client) close_client(client) assert_new_connections_work end - it 'must not timeout per sql batch when not under transaction' do - client = new_connection :timeout => 2 + it "must not timeout per sql batch when not under transaction" do + client = new_connection timeout: 2 client.execute("WaitFor Delay '00:00:01'").do client.execute("WaitFor Delay '00:00:01'").do client.execute("WaitFor Delay '00:00:01'").do close_client(client) end - it 'must not timeout per sql batch when under transaction' do - client = new_connection :timeout => 2 + it "must not timeout per sql batch when under transaction" do + client = new_connection timeout: 2 begin client.execute("BEGIN TRANSACTION").do client.execute("WaitFor Delay '00:00:01'").do @@ -130,32 +129,30 @@ class ClientTest < TinyTds::TestCase end end - it 'raises TinyTds exception with tcp socket network failure' do - begin - client = new_connection timeout: 2, port: 1234, host: ENV['TOXIPROXY_HOST'] - assert_client_works(client) - action = lambda { client.execute("waitfor delay '00:00:05'").do } + it "raises TinyTds exception with tcp socket network failure" do + client = new_connection timeout: 2, port: 1234, host: ENV["TOXIPROXY_HOST"] + assert_client_works(client) + action = lambda { client.execute("waitfor delay '00:00:05'").do } - # Use toxiproxy to close the TCP socket after 1 second. - # We want TinyTds to execute the statement, hit the timeout configured above, and then not be able to use the network to cancel - # the network connection needs to close after the sql batch is sent and before the timeout above is hit - Toxiproxy[:sqlserver_test].toxic(:slow_close, delay: 1000).apply do - assert_raise_tinytds_error(action) do |e| - assert_equal 20003, e.db_error_number - assert_equal 6, e.severity - assert_match %r{timed out}i, e.message, 'ignore if non-english test run' - end + # Use toxiproxy to close the TCP socket after 1 second. + # We want TinyTds to execute the statement, hit the timeout configured above, and then not be able to use the network to cancel + # the network connection needs to close after the sql batch is sent and before the timeout above is hit + Toxiproxy[:sqlserver_test].toxic(:slow_close, delay: 1000).apply do + assert_raise_tinytds_error(action) do |e| + assert_equal 20003, e.db_error_number + assert_equal 6, e.severity + assert_match %r{timed out}i, e.message, "ignore if non-english test run" end - ensure - assert_new_connections_work end + ensure + assert_new_connections_work end - it 'raises TinyTds exception with dead connection network failure' do + it "raises TinyTds exception with dead connection network failure" do skip if ruby_windows? begin - client = new_connection timeout: 2, port: 1234, host: ENV['TOXIPROXY_HOST'] + client = new_connection timeout: 2, port: 1234, host: ENV["TOXIPROXY_HOST"] assert_client_works(client) action = lambda { client.execute("waitfor delay '00:00:05'").do } @@ -165,8 +162,8 @@ class ClientTest < TinyTds::TestCase Toxiproxy[:sqlserver_test].toxic(:timeout, timeout: 1000).apply do assert_raise_tinytds_error(action) do |e| assert_equal 20047, e.db_error_number - assert_includes [1,9], e.severity - assert_match %r{dead or not enabled}i, e.message, 'ignore if non-english test run' + assert_includes [1, 9], e.severity + assert_match %r{dead or not enabled}i, e.message, "ignore if non-english test run" end end ensure @@ -174,99 +171,96 @@ class ClientTest < TinyTds::TestCase end end - it 'raises TinyTds exception with login timeout' do - begin - action = lambda do - Toxiproxy[:sqlserver_test].toxic(:timeout, timeout: 0).apply do - new_connection login_timeout: 1, port: 1234, host: ENV['TOXIPROXY_HOST'] - end - end - assert_raise_tinytds_error(action) do |e| - assert_equal 20003, e.db_error_number - assert_equal 6, e.severity - assert_match %r{timed out}i, e.message, 'ignore if non-english test run' + it "raises TinyTds exception with login timeout" do + action = lambda do + Toxiproxy[:sqlserver_test].toxic(:timeout, timeout: 0).apply do + new_connection login_timeout: 1, port: 1234, host: ENV["TOXIPROXY_HOST"] end - ensure - assert_new_connections_work end + assert_raise_tinytds_error(action) do |e| + assert_equal 20003, e.db_error_number + assert_equal 6, e.severity + assert_match %r{timed out}i, e.message, "ignore if non-english test run" + end + ensure + assert_new_connections_work end - it 'raises TinyTds exception with wrong :username' do - skip if ENV['CI'] && sqlserver_azure? # Some issue with db_error_number. - options = connection_options :username => 'willnotwork' + it "raises TinyTds exception with wrong :username" do + skip if ENV["CI"] && sqlserver_azure? # Some issue with db_error_number. + options = connection_options username: "willnotwork" action = lambda { new_connection(options) } assert_raise_tinytds_error(action) do |e| assert_equal 18456, e.db_error_number assert_equal 14, e.severity - assert_match %r{login failed}i, e.message, 'ignore if non-english test run' + assert_match %r{login failed}i, e.message, "ignore if non-english test run" end assert_new_connections_work end - end - describe '#parse_username' do + describe "#parse_username" do let(:client) { @client = new_connection } - it 'returns username if azure is not true' do + it "returns username if azure is not true" do _( - client.send(:parse_username, username: 'user@abc123.database.windows.net') - ).must_equal 'user@abc123.database.windows.net' + client.send(:parse_username, username: "user@abc123.database.windows.net") + ).must_equal "user@abc123.database.windows.net" end - it 'returns short username if azure is true' do + it "returns short username if azure is true" do _( client.send( :parse_username, - username: 'user@abc123.database.windows.net', - host: 'abc123.database.windows.net', - azure: true + username: "user@abc123.database.windows.net", + host: "abc123.database.windows.net", + azure: true ) - ).must_equal 'user@abc123' + ).must_equal "user@abc123" end - it 'returns full username if azure is false' do + it "returns full username if azure is false" do _( client.send( :parse_username, - username: 'user@abc123.database.windows.net', - host: 'abc123.database.windows.net', - azure: false + username: "user@abc123.database.windows.net", + host: "abc123.database.windows.net", + azure: false ) - ).must_equal 'user@abc123.database.windows.net' + ).must_equal "user@abc123.database.windows.net" end - it 'returns short username if passed and azure is true' do + it "returns short username if passed and azure is true" do _( client.send( :parse_username, - username: 'user@abc123', - host: 'abc123.database.windows.net', - azure: true + username: "user@abc123", + host: "abc123.database.windows.net", + azure: true ) - ).must_equal 'user@abc123' + ).must_equal "user@abc123" end - it 'returns username with servername if passed and azure is true' do + it "returns username with servername if passed and azure is true" do _( client.send( :parse_username, - username: 'user', - host: 'abc123.database.windows.net', - azure: true + username: "user", + host: "abc123.database.windows.net", + azure: true ) - ).must_equal 'user@abc123' + ).must_equal "user@abc123" end - it 'returns username with servername if passed and azure is false' do + it "returns username with servername if passed and azure is false" do _( client.send( :parse_username, - username: 'user', - host: 'abc123.database.windows.net', - azure: false + username: "user", + host: "abc123.database.windows.net", + azure: false ) - ).must_equal 'user' + ).must_equal "user" end end end diff --git a/test/gem_test.rb b/test/gem_test.rb index eea45623..9d2f1b0e 100644 --- a/test/gem_test.rb +++ b/test/gem_test.rb @@ -1,67 +1,65 @@ -# encoding: utf-8 -require 'test_helper' -require 'tiny_tds/gem' +require "test_helper" +require "tiny_tds/gem" class GemTest < Minitest::Spec - gem_root ||= File.expand_path '../..', __FILE__ + gem_root ||= File.expand_path "../..", __FILE__ describe TinyTds::Gem do - # We're going to muck with some system globals so lets make sure # they get set back later - original_platform = RbConfig::CONFIG['arch'] + original_platform = RbConfig::CONFIG["arch"] original_pwd = Dir.pwd after do - RbConfig::CONFIG['arch'] = original_platform + RbConfig::CONFIG["arch"] = original_platform Dir.chdir original_pwd end - describe '#root_path' do + describe "#root_path" do let(:root_path) { TinyTds::Gem.root_path } - it 'should be the root path' do + it "should be the root path" do _(root_path).must_equal gem_root end - it 'should be the root path no matter the cwd' do - Dir.chdir '/' + it "should be the root path no matter the cwd" do + Dir.chdir "/" _(root_path).must_equal gem_root end end - describe '#ports_root_path' do + describe "#ports_root_path" do let(:ports_root_path) { TinyTds::Gem.ports_root_path } - it 'should be the ports path' do - _(ports_root_path).must_equal File.join(gem_root,'ports') + it "should be the ports path" do + _(ports_root_path).must_equal File.join(gem_root, "ports") end - it 'should be the ports path no matter the cwd' do - Dir.chdir '/' + it "should be the ports path no matter the cwd" do + Dir.chdir "/" - _(ports_root_path).must_equal File.join(gem_root,'ports') + _(ports_root_path).must_equal File.join(gem_root, "ports") end end - describe '#ports_bin_paths' do + describe "#ports_bin_paths" do let(:ports_bin_paths) { TinyTds::Gem.ports_bin_paths } - describe 'when the ports directories exist' do + describe "when the ports directories exist" do let(:fake_bin_paths) do - ports_host_root = File.join(gem_root, 'ports', 'fake-host-with-dirs') + ports_host_root = File.join(gem_root, "ports", "fake-host-with-dirs") [ - File.join('a','bin'), - File.join('a','inner','bin'), - File.join('b','bin') + File.join("a", "bin"), + File.join("a", "inner", "bin"), + File.join("b", "bin") ].map do |p| File.join(ports_host_root, p) end end before do - RbConfig::CONFIG['arch'] = 'fake-host-with-dirs' + RbConfig::CONFIG["arch"] = "fake-host-with-dirs" fake_bin_paths.each do |path| FileUtils.mkdir_p(path) end @@ -69,35 +67,34 @@ class GemTest < Minitest::Spec after do FileUtils.remove_entry_secure( - File.join(gem_root, 'ports', 'fake-host-with-dirs'), true + File.join(gem_root, "ports", "fake-host-with-dirs"), true ) end - it 'should return all the bin directories' do + it "should return all the bin directories" do _(ports_bin_paths.sort).must_equal fake_bin_paths.sort end - it 'should return all the bin directories regardless of cwd' do - Dir.chdir '/' + it "should return all the bin directories regardless of cwd" do + Dir.chdir "/" _(ports_bin_paths.sort).must_equal fake_bin_paths.sort end end - describe 'when the ports directories are missing' do + describe "when the ports directories are missing" do before do - RbConfig::CONFIG['arch'] = 'fake-host-without-dirs' + RbConfig::CONFIG["arch"] = "fake-host-without-dirs" end - it 'should return no directories' do + it "should return no directories" do _(ports_bin_paths).must_be_empty end - it 'should return no directories regardless of cwd' do - Dir.chdir '/' + it "should return no directories regardless of cwd" do + Dir.chdir "/" _(ports_bin_paths).must_be_empty end end end end end - diff --git a/test/result_test.rb b/test/result_test.rb index 1d054f92..6f9bb109 100644 --- a/test/result_test.rb +++ b/test/result_test.rb @@ -1,43 +1,40 @@ -# encoding: utf-8 -require 'test_helper' +require "test_helper" class ResultTest < TinyTds::TestCase - - describe 'Basic query and result' do - + describe "Basic query and result" do before do @@current_schema_loaded ||= load_current_schema @client = new_connection - @query1 = 'SELECT 1 AS [one]' + @query1 = "SELECT 1 AS [one]" end - it 'has included Enumerable' do + it "has included Enumerable" do assert TinyTds::Result.ancestors.include?(Enumerable) end - it 'responds to #each' do + it "responds to #each" do result = @client.execute(@query1) assert result.respond_to?(:each) end - it 'returns all results for #each with no block' do + it "returns all results for #each with no block" do result = @client.execute(@query1) data = result.each row = data.first assert_instance_of Array, data assert_equal 1, data.size - assert_instance_of Hash, row, 'hash is the default query option' + assert_instance_of Hash, row, "hash is the default query option" end - it 'returns all results for #each with a block yielding a row at a time' do + it "returns all results for #each with a block yielding a row at a time" do result = @client.execute(@query1) data = result.each do |row| - assert_instance_of Hash, row, 'hash is the default query option' + assert_instance_of Hash, row, "hash is the default query option" end assert_instance_of Array, data end - it 'allows successive calls to each returning the same data' do + it "allows successive calls to each returning the same data" do result = @client.execute(@query1) data = result.each result.each @@ -45,150 +42,150 @@ class ResultTest < TinyTds::TestCase assert_equal data.first.object_id, result.each.first.object_id end - it 'returns hashes with string keys' do + it "returns hashes with string keys" do result = @client.execute(@query1) - row = result.each(:as => :hash, :symbolize_keys => false).first + row = result.each(as: :hash, symbolize_keys: false).first assert_instance_of Hash, row - assert_equal ['one'], row.keys - assert_equal ['one'], result.fields + assert_equal ["one"], row.keys + assert_equal ["one"], result.fields end - it 'returns hashes with symbol keys' do + it "returns hashes with symbol keys" do result = @client.execute(@query1) - row = result.each(:as => :hash, :symbolize_keys => true).first + row = result.each(as: :hash, symbolize_keys: true).first assert_instance_of Hash, row assert_equal [:one], row.keys assert_equal [:one], result.fields end - it 'returns arrays with string fields' do + it "returns arrays with string fields" do result = @client.execute(@query1) - row = result.each(:as => :array, :symbolize_keys => false).first + row = result.each(as: :array, symbolize_keys: false).first assert_instance_of Array, row - assert_equal ['one'], result.fields + assert_equal ["one"], result.fields end - it 'returns arrays with symbol fields' do + it "returns arrays with symbol fields" do result = @client.execute(@query1) - row = result.each(:as => :array, :symbolize_keys => true).first + row = result.each(as: :array, symbolize_keys: true).first assert_instance_of Array, row assert_equal [:one], result.fields end - it 'allows sql concat + to work' do + it "allows sql concat + to work" do rollback_transaction(@client) do @client.execute("DELETE FROM [datatypes]").do @client.execute("INSERT INTO [datatypes] ([char_10], [varchar_50]) VALUES ('1', '2')").do - result = @client.execute("SELECT TOP (1) [char_10] + 'test' + [varchar_50] AS [test] FROM [datatypes]").each.first['test'] + result = @client.execute("SELECT TOP (1) [char_10] + 'test' + [varchar_50] AS [test] FROM [datatypes]").each.first["test"] _(result).must_equal "1 test2" end end - it 'must be able to turn :cache_rows option off' do + it "must be able to turn :cache_rows option off" do result = @client.execute(@query1) local = [] - result.each(:cache_rows => false) do |row| + result.each(cache_rows: false) do |row| local << row end - assert local.first, 'should have iterated over each row' - assert_equal [], result.each, 'should not have been cached' - assert_equal ['one'], result.fields, 'should still cache field names' + assert local.first, "should have iterated over each row" + assert_equal [], result.each, "should not have been cached" + assert_equal ["one"], result.fields, "should still cache field names" end - it 'must be able to get the first result row only' do + it "must be able to get the first result row only" do load_current_schema big_query = "SELECT [id] FROM [datatypes]" - one = @client.execute(big_query).each(:first => true) + one = @client.execute(big_query).each(first: true) many = @client.execute(big_query).each assert many.size > 1 assert one.size == 1 end - it 'copes with no results when using first option' do - data = @client.execute("SELECT [id] FROM [datatypes] WHERE [id] = -1").each(:first => true) + it "copes with no results when using first option" do + data = @client.execute("SELECT [id] FROM [datatypes] WHERE [id] = -1").each(first: true) assert_equal [], data end - it 'must delete, insert and find data' do + it "must delete, insert and find data" do rollback_transaction(@client) do - text = 'test insert and delete' + text = "test insert and delete" @client.execute("DELETE FROM [datatypes] WHERE [varchar_50] IS NOT NULL").do @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do row = @client.execute("SELECT [varchar_50] FROM [datatypes] WHERE [varchar_50] IS NOT NULL").each.first assert row - assert_equal text, row['varchar_50'] + assert_equal text, row["varchar_50"] end end - it 'must insert and find unicode data' do + it "must insert and find unicode data" do rollback_transaction(@client) do - text = '😍' + text = "😍" @client.execute("DELETE FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").do @client.execute("INSERT INTO [datatypes] ([nvarchar_50]) VALUES (N'#{text}')").do row = @client.execute("SELECT [nvarchar_50] FROM [datatypes] WHERE [nvarchar_50] IS NOT NULL").each.first - assert_equal text, row['nvarchar_50'] + assert_equal text, row["nvarchar_50"] end end - it 'must delete and update with affected rows support and insert with identity support in native sql' do + it "must delete and update with affected rows support and insert with identity support in native sql" do rollback_transaction(@client) do - text = 'test affected rows sql' + text = "test affected rows sql" @client.execute("DELETE FROM [datatypes]").do - afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first['AffectedRows'] - _(['Fixnum', 'Integer']).must_include afrows.class.name + afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first["AffectedRows"] + _(["Fixnum", "Integer"]).must_include afrows.class.name @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do - pk1 = @client.execute(@client.identity_sql).each.first['Ident'] - _(['Fixnum', 'Integer']).must_include pk1.class.name, 'we it be able to CAST to bigint' + pk1 = @client.execute(@client.identity_sql).each.first["Ident"] + _(["Fixnum", "Integer"]).must_include pk1.class.name, "we it be able to CAST to bigint" @client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do - afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first['AffectedRows'] + afrows = @client.execute("SELECT @@ROWCOUNT AS AffectedRows").each.first["AffectedRows"] assert_equal 1, afrows end end - it 'has a #do method that cancels result rows and returns affected rows natively' do + it "has a #do method that cancels result rows and returns affected rows natively" do rollback_transaction(@client) do - text = 'test affected rows native' - count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count'] + text = "test affected rows native" + count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first["count"] deleted_rows = @client.execute("DELETE FROM [datatypes]").do - assert_equal count, deleted_rows, 'should have deleted rows equal to count' + assert_equal count, deleted_rows, "should have deleted rows equal to count" inserted_rows = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do - assert_equal 1, inserted_rows, 'should have inserted row for one above' + assert_equal 1, inserted_rows, "should have inserted row for one above" updated_rows = @client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do - assert_equal 1, updated_rows, 'should have updated row for one above' + assert_equal 1, updated_rows, "should have updated row for one above" end end - it 'allows native affected rows using #do to work under transaction' do + it "allows native affected rows using #do to work under transaction" do rollback_transaction(@client) do - text = 'test affected rows native in transaction' + text = "test affected rows native in transaction" @client.execute("BEGIN TRANSACTION").do @client.execute("DELETE FROM [datatypes]").do inserted_rows = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do - assert_equal 1, inserted_rows, 'should have inserted row for one above' + assert_equal 1, inserted_rows, "should have inserted row for one above" updated_rows = @client.execute("UPDATE [datatypes] SET [varchar_50] = NULL WHERE [varchar_50] = '#{text}'").do - assert_equal 1, updated_rows, 'should have updated row for one above' + assert_equal 1, updated_rows, "should have updated row for one above" end end - it 'has an #insert method that cancels result rows and returns IDENTITY natively' do + it "has an #insert method that cancels result rows and returns IDENTITY natively" do rollback_transaction(@client) do - text = 'test scope identity rows native' + text = "test scope identity rows native" @client.execute("DELETE FROM [datatypes] WHERE [varchar_50] = '#{text}'").do @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").do - sql_identity = @client.execute(@client.identity_sql).each.first['Ident'] + sql_identity = @client.execute(@client.identity_sql).each.first["Ident"] native_identity = @client.execute("INSERT INTO [datatypes] ([varchar_50]) VALUES ('#{text}')").insert assert_equal sql_identity + 1, native_identity end end - it 'returns bigint for #insert when needed' do + it "returns bigint for #insert when needed" do return if sqlserver_azure? # We can not alter clustered index like this test does. # 'CREATE TABLE' command is not allowed within a multi-statement transaction # and and sp_helpindex creates a temporary table #spindtab. rollback_transaction(@client) do seed = 9223372036854775805 @client.execute("DELETE FROM [datatypes]").do - id_constraint_name = @client.execute("EXEC sp_helpindex [datatypes]").detect { |row| row['index_keys'] == 'id' }['index_name'] + id_constraint_name = @client.execute("EXEC sp_helpindex [datatypes]").detect { |row| row["index_keys"] == "id" }["index_name"] @client.execute("ALTER TABLE [datatypes] DROP CONSTRAINT [#{id_constraint_name}]").do @client.execute("ALTER TABLE [datatypes] DROP COLUMN [id]").do @client.execute("ALTER TABLE [datatypes] ADD [id] [bigint] NOT NULL IDENTITY(1,1) PRIMARY KEY").do @@ -198,59 +195,59 @@ class ResultTest < TinyTds::TestCase end end - it 'must be able to begin/commit transactions with raw sql' do + it "must be able to begin/commit transactions with raw sql" do rollback_transaction(@client) do @client.execute("BEGIN TRANSACTION").do @client.execute("DELETE FROM [datatypes]").do @client.execute("COMMIT TRANSACTION").do - count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count'] + count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first["count"] assert_equal 0, count end end - it 'must be able to begin/rollback transactions with raw sql' do + it "must be able to begin/rollback transactions with raw sql" do load_current_schema @client.execute("BEGIN TRANSACTION").do @client.execute("DELETE FROM [datatypes]").do @client.execute("ROLLBACK TRANSACTION").do - count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first['count'] + count = @client.execute("SELECT COUNT(*) AS [count] FROM [datatypes]").each.first["count"] _(count).wont_equal 0 end - it 'has a #fields accessor with logic default and valid outcome' do + it "has a #fields accessor with logic default and valid outcome" do result = @client.execute(@query1) - _(result.fields).must_equal ['one'] + _(result.fields).must_equal ["one"] result.each - _(result.fields).must_equal ['one'] + _(result.fields).must_equal ["one"] end - it 'always returns an array for fields for all sql' do + it "always returns an array for fields for all sql" do result = @client.execute("USE [tinytdstest]") _(result.fields).must_equal [] result.do _(result.fields).must_equal [] end - it 'returns fields even when no results are found' do + it "returns fields even when no results are found" do no_results_query = "SELECT [id], [varchar_50] FROM [datatypes] WHERE [varchar_50] = 'NOTFOUND'" # Fields before each. result = @client.execute(no_results_query) - _(result.fields).must_equal ['id', 'varchar_50'] + _(result.fields).must_equal ["id", "varchar_50"] result.each - _(result.fields).must_equal ['id', 'varchar_50'] + _(result.fields).must_equal ["id", "varchar_50"] # Each then fields result = @client.execute(no_results_query) result.each - _(result.fields).must_equal ['id', 'varchar_50'] + _(result.fields).must_equal ["id", "varchar_50"] end - it 'allows the result to be canceled before reading' do + it "allows the result to be canceled before reading" do result = @client.execute(@query1) result.cancel @client.execute(@query1).each end - it 'works in tandem with the client when needing to find out if client has sql sent and result is canceled or not' do + it "works in tandem with the client when needing to find out if client has sql sent and result is canceled or not" do # Default state. @client = TinyTds::Client.new(connection_options) _(@client.sqlsent?).must_equal false @@ -262,21 +259,21 @@ class ResultTest < TinyTds::TestCase result.cancel _(@client.sqlsent?).must_equal false _(@client.canceled?).must_equal true - assert result.cancel, 'must be safe to call again' + assert result.cancel, "must be safe to call again" # With each and no block. @client.execute(@query1).each _(@client.sqlsent?).must_equal false _(@client.canceled?).must_equal false # With each and block. @client.execute(@query1).each do |row| - _(@client.sqlsent?).must_equal true, 'when iterating over each row in a block' + _(@client.sqlsent?).must_equal true, "when iterating over each row in a block" _(@client.canceled?).must_equal false end _(@client.sqlsent?).must_equal false _(@client.canceled?).must_equal false # With each and block canceled half way thru. - count = @client.execute("SELECT COUNT([id]) AS [count] FROM [datatypes]").each[0]['count'] - assert count > 10, 'since we want to cancel early for test' + count = @client.execute("SELECT COUNT([id]) AS [count] FROM [datatypes]").each[0]["count"] + assert count > 10, "since we want to cancel early for test" result = @client.execute("SELECT [id] FROM [datatypes]") index = 0 result.each do |row| @@ -299,48 +296,51 @@ class ResultTest < TinyTds::TestCase _(@client.canceled?).must_equal true end # With first - @client.execute("SELECT [id] FROM [datatypes]").each(:first => true) + @client.execute("SELECT [id] FROM [datatypes]").each(first: true) _(@client.sqlsent?).must_equal false _(@client.canceled?).must_equal true end - it 'use same string object for hash keys' do + it "use same string object for hash keys" do data = @client.execute("SELECT [id], [bigint] FROM [datatypes]").each assert_equal data.first.keys.map { |r| r.object_id }, data.last.keys.map { |r| r.object_id } end - it 'has properly encoded column names with symbol keys' do + it "has properly encoded column names with symbol keys" do col_name = "öäüß" - @client.execute("DROP TABLE [test_encoding]").do rescue nil + begin + @client.execute("DROP TABLE [test_encoding]").do + rescue + nil + end @client.execute("CREATE TABLE [dbo].[test_encoding] ( [id] int NOT NULL IDENTITY(1,1) PRIMARY KEY, [#{col_name}] [nvarchar](10) NOT NULL )").do @client.execute("INSERT INTO [test_encoding] ([#{col_name}]) VALUES (N'#{col_name}')").do result = @client.execute("SELECT [#{col_name}] FROM [test_encoding]") - row = result.each(:as => :hash, :symbolize_keys => true).first + row = result.each(as: :hash, symbolize_keys: true).first assert_instance_of Symbol, result.fields.first assert_equal col_name.to_sym, result.fields.first assert_instance_of Symbol, row.keys.first assert_equal col_name.to_sym, row.keys.first end - it 'allows #return_code to work with stored procedures and reset per sql batch' do + it "allows #return_code to work with stored procedures and reset per sql batch" do assert_nil @client.return_code result = @client.execute("EXEC tinytds_TestReturnCodes") - assert_equal [{ "one" => 1 }], result.each + assert_equal [{"one" => 1}], result.each assert_equal 420, @client.return_code assert_equal 420, result.return_code - result = @client.execute('SELECT 1 as [one]') + result = @client.execute("SELECT 1 as [one]") result.each assert_nil @client.return_code assert_nil result.return_code end - it 'with LOGINPROPERTY function' do - v = @client.execute("SELECT LOGINPROPERTY('sa', 'IsLocked') as v").first['v'] + it "with LOGINPROPERTY function" do + v = @client.execute("SELECT LOGINPROPERTY('sa', 'IsLocked') as v").first["v"] _(v).must_equal 0 end - describe 'with multiple result sets' do - + describe "with multiple result sets" do before do @empty_select = "SELECT 1 AS [rs1] WHERE 1 = 0" @double_select = "SELECT 1 AS [rs1] @@ -356,42 +356,41 @@ class ResultTest < TinyTds::TestCase SELECT 3 AS [rs3] WHERE 1 = 0" end - it 'handles a command buffer with double selects' do + it "handles a command buffer with double selects" do result = @client.execute(@double_select) result_sets = result.each assert_equal 2, result_sets.size - assert_equal [{ 'rs1' => 1 }], result_sets.first - assert_equal [{ 'rs2' => 2 }], result_sets.last - assert_equal [['rs1'], ['rs2']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [{"rs1" => 1}], result_sets.first + assert_equal [{"rs2" => 2}], result_sets.last + assert_equal [["rs1"], ["rs2"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" # As array result = @client.execute(@double_select) - result_sets = result.each(:as => :array) + result_sets = result.each(as: :array) assert_equal 2, result_sets.size assert_equal [[1]], result_sets.first assert_equal [[2]], result_sets.last - assert_equal [['rs1'], ['rs2']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [["rs1"], ["rs2"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" end - it 'yields each row for each result set' do + it "yields each row for each result set" do data = [] result_sets = @client.execute(@double_select).each { |row| data << row } assert_equal data.first, result_sets.first[0] assert_equal data.last, result_sets.last[0] end - it 'works from a stored procedure' do + it "works from a stored procedure" do results1, results2 = @client.execute("EXEC sp_helpconstraint '[datatypes]'").each - assert_equal [{ "Object Name" => "[datatypes]" }], results1 + assert_equal [{"Object Name" => "[datatypes]"}], results1 constraint_info = results2.first assert constraint_info.key?("constraint_keys") assert constraint_info.key?("constraint_type") assert constraint_info.key?("constraint_name") end - describe 'using :empty_sets TRUE' do - + describe "using :empty_sets TRUE" do before do close_client @old_query_option_value = TinyTds::Client.default_query_options[:empty_sets] @@ -403,76 +402,74 @@ class ResultTest < TinyTds::TestCase TinyTds::Client.default_query_options[:empty_sets] = @old_query_option_value end - it 'handles a basic empty result set' do + it "handles a basic empty result set" do result = @client.execute(@empty_select) assert_equal [], result.each - assert_equal ['rs1'], result.fields + assert_equal ["rs1"], result.fields end - it 'includes empty result sets by default - using 1st empty buffer' do + it "includes empty result sets by default - using 1st empty buffer" do result = @client.execute(@triple_select_1st_empty) result_sets = result.each assert_equal 3, result_sets.size assert_equal [], result_sets[0] - assert_equal [{ 'rs2' => 2 }], result_sets[1] - assert_equal [{ 'rs3' => 3 }], result_sets[2] - assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [{"rs2" => 2}], result_sets[1] + assert_equal [{"rs3" => 3}], result_sets[2] + assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" # As array result = @client.execute(@triple_select_1st_empty) - result_sets = result.each(:as => :array) + result_sets = result.each(as: :array) assert_equal 3, result_sets.size assert_equal [], result_sets[0] assert_equal [[2]], result_sets[1] assert_equal [[3]], result_sets[2] - assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" end - it 'includes empty result sets by default - using 2nd empty buffer' do + it "includes empty result sets by default - using 2nd empty buffer" do result = @client.execute(@triple_select_2nd_empty) result_sets = result.each assert_equal 3, result_sets.size - assert_equal [{ 'rs1' => 1 }], result_sets[0] + assert_equal [{"rs1" => 1}], result_sets[0] assert_equal [], result_sets[1] - assert_equal [{ 'rs3' => 3 }], result_sets[2] - assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [{"rs3" => 3}], result_sets[2] + assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" # As array result = @client.execute(@triple_select_2nd_empty) - result_sets = result.each(:as => :array) + result_sets = result.each(as: :array) assert_equal 3, result_sets.size assert_equal [[1]], result_sets[0] assert_equal [], result_sets[1] assert_equal [[3]], result_sets[2] - assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" end - it 'includes empty result sets by default - using 3rd empty buffer' do + it "includes empty result sets by default - using 3rd empty buffer" do result = @client.execute(@triple_select_3rd_empty) result_sets = result.each assert_equal 3, result_sets.size - assert_equal [{ 'rs1' => 1 }], result_sets[0] - assert_equal [{ 'rs2' => 2 }], result_sets[1] + assert_equal [{"rs1" => 1}], result_sets[0] + assert_equal [{"rs2" => 2}], result_sets[1] assert_equal [], result_sets[2] - assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" # As array result = @client.execute(@triple_select_3rd_empty) - result_sets = result.each(:as => :array) + result_sets = result.each(as: :array) assert_equal 3, result_sets.size assert_equal [[1]], result_sets[0] assert_equal [[2]], result_sets[1] assert_equal [], result_sets[2] - assert_equal [['rs1'], ['rs2'], ['rs3']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [["rs1"], ["rs2"], ["rs3"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" end - end - describe 'using :empty_sets FALSE' do - + describe "using :empty_sets FALSE" do before do close_client @old_query_option_value = TinyTds::Client.default_query_options[:empty_sets] @@ -484,169 +481,160 @@ class ResultTest < TinyTds::TestCase TinyTds::Client.default_query_options[:empty_sets] = @old_query_option_value end - it 'handles a basic empty result set' do + it "handles a basic empty result set" do result = @client.execute(@empty_select) assert_equal [], result.each - assert_equal ['rs1'], result.fields + assert_equal ["rs1"], result.fields end - it 'must not include empty result sets by default - using 1st empty buffer' do + it "must not include empty result sets by default - using 1st empty buffer" do result = @client.execute(@triple_select_1st_empty) result_sets = result.each assert_equal 2, result_sets.size - assert_equal [{ 'rs2' => 2 }], result_sets[0] - assert_equal [{ 'rs3' => 3 }], result_sets[1] - assert_equal [['rs2'], ['rs3']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [{"rs2" => 2}], result_sets[0] + assert_equal [{"rs3" => 3}], result_sets[1] + assert_equal [["rs2"], ["rs3"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" # As array result = @client.execute(@triple_select_1st_empty) - result_sets = result.each(:as => :array) + result_sets = result.each(as: :array) assert_equal 2, result_sets.size assert_equal [[2]], result_sets[0] assert_equal [[3]], result_sets[1] - assert_equal [['rs2'], ['rs3']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [["rs2"], ["rs3"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" end - it 'must not include empty result sets by default - using 2nd empty buffer' do + it "must not include empty result sets by default - using 2nd empty buffer" do result = @client.execute(@triple_select_2nd_empty) result_sets = result.each assert_equal 2, result_sets.size - assert_equal [{ 'rs1' => 1 }], result_sets[0] - assert_equal [{ 'rs3' => 3 }], result_sets[1] - assert_equal [['rs1'], ['rs3']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [{"rs1" => 1}], result_sets[0] + assert_equal [{"rs3" => 3}], result_sets[1] + assert_equal [["rs1"], ["rs3"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" # As array result = @client.execute(@triple_select_2nd_empty) - result_sets = result.each(:as => :array) + result_sets = result.each(as: :array) assert_equal 2, result_sets.size assert_equal [[1]], result_sets[0] assert_equal [[3]], result_sets[1] - assert_equal [['rs1'], ['rs3']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [["rs1"], ["rs3"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" end - it 'must not include empty result sets by default - using 3rd empty buffer' do + it "must not include empty result sets by default - using 3rd empty buffer" do result = @client.execute(@triple_select_3rd_empty) result_sets = result.each assert_equal 2, result_sets.size - assert_equal [{ 'rs1' => 1 }], result_sets[0] - assert_equal [{ 'rs2' => 2 }], result_sets[1] - assert_equal [['rs1'], ['rs2']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [{"rs1" => 1}], result_sets[0] + assert_equal [{"rs2" => 2}], result_sets[1] + assert_equal [["rs1"], ["rs2"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" # As array result = @client.execute(@triple_select_3rd_empty) - result_sets = result.each(:as => :array) + result_sets = result.each(as: :array) assert_equal 2, result_sets.size assert_equal [[1]], result_sets[0] assert_equal [[2]], result_sets[1] - assert_equal [['rs1'], ['rs2']], result.fields - assert_equal result.each.object_id, result.each.object_id, 'same cached rows' + assert_equal [["rs1"], ["rs2"]], result.fields + assert_equal result.each.object_id, result.each.object_id, "same cached rows" end - end - end - describe 'Complex query with multiple results sets but no actual results' do + unless sqlserver_azure? + describe "Complex query with multiple results sets but no actual results" do + let(:backup_file) { 'C:\\Users\\Public\\tinytdstest.bak' } - let(:backup_file) { 'C:\\Users\\Public\\tinytdstest.bak' } + after { File.delete(backup_file) if File.exist?(backup_file) } - after { File.delete(backup_file) if File.exist?(backup_file) } - - it 'must not cancel the query until complete' do - @client.execute("BACKUP DATABASE tinytdstest TO DISK = '#{backup_file}'").do + it "must not cancel the query until complete" do + @client.execute("BACKUP DATABASE tinytdstest TO DISK = '#{backup_file}'").do + end end + end - end unless sqlserver_azure? - - describe 'when casting to native ruby values' do - - it 'returns fixnum for 1' do - value = @client.execute('SELECT 1 AS [fixnum]').each.first['fixnum'] + describe "when casting to native ruby values" do + it "returns fixnum for 1" do + value = @client.execute("SELECT 1 AS [fixnum]").each.first["fixnum"] assert_equal 1, value end - it 'returns nil for NULL' do - value = @client.execute('SELECT NULL AS [null]').each.first['null'] + it "returns nil for NULL" do + value = @client.execute("SELECT NULL AS [null]").each.first["null"] assert_nil value end - end - describe 'with data type' do - - describe 'char max' do - + describe "with data type" do + describe "char max" do before do - @big_text = 'x' * 2_000_000 - @old_textsize = @client.execute("SELECT @@TEXTSIZE AS [textsize]").each.first['textsize'].inspect + @big_text = "x" * 2_000_000 + @old_textsize = @client.execute("SELECT @@TEXTSIZE AS [textsize]").each.first["textsize"].inspect @client.execute("SET TEXTSIZE #{(@big_text.length * 2) + 1}").do end - it 'must insert and select large varchar_max' do + it "must insert and select large varchar_max" do insert_and_select_datatype :varchar_max end - it 'must insert and select large nvarchar_max' do + it "must insert and select large nvarchar_max" do insert_and_select_datatype :nvarchar_max end - end - end - describe 'when shit happens' do - - it 'copes with nil or empty buffer' do + describe "when shit happens" do + it "copes with nil or empty buffer" do assert_raises(TypeError) { @client.execute(nil) } - assert_equal [], @client.execute('').each + assert_equal [], @client.execute("").each end - describe 'using :message_handler option' do - let(:messages) { Array.new } + describe "using :message_handler option" do + let(:messages) { [] } before do close_client - @client = new_connection message_handler: Proc.new { |m| messages << m } + @client = new_connection message_handler: proc { |m| messages << m } end after do messages.clear end - it 'has a message handler that responds to call' do + it "has a message handler that responds to call" do assert @client.message_handler.respond_to?(:call) end - it 'calls the provided message handler when severity is 10 or less' do + it "calls the provided message handler when severity is 10 or less" do (1..10).to_a.each do |severity| messages.clear msg = "Test #{severity} severity" state = rand(1..255) @client.execute("RAISERROR(N'#{msg}', #{severity}, #{state})").do m = messages.first - assert_equal 1, messages.length, 'there should be one message after one raiserror' - assert_equal msg, m.message, 'message text' - assert_equal severity, m.severity, 'message severity' unless severity == 10 && m.severity.to_i == 0 - assert_equal state, m.os_error_number, 'message state' + assert_equal 1, messages.length, "there should be one message after one raiserror" + assert_equal msg, m.message, "message text" + assert_equal severity, m.severity, "message severity" unless severity == 10 && m.severity.to_i == 0 + assert_equal state, m.os_error_number, "message state" end end - it 'calls the provided message handler for `print` messages' do + it "calls the provided message handler for `print` messages" do messages.clear - msg = 'hello' + msg = "hello" @client.execute("PRINT '#{msg}'").do m = messages.first - assert_equal 1, messages.length, 'there should be one message after one print statement' - assert_equal msg, m.message, 'message text' + assert_equal 1, messages.length, "there should be one message after one print statement" + assert_equal msg, m.message, "message text" end - it 'must raise an error preceded by a `print` message' do + it "must raise an error preceded by a `print` message" do messages.clear action = lambda { @client.execute("EXEC tinytds_TestPrintWithError").do } assert_raise_tinytds_error(action) do |e| - assert_equal 'hello', messages.first.message, 'message text' + assert_equal "hello", messages.first.message, "message text" assert_equal "Error following print", e.message assert_equal 16, e.severity @@ -654,44 +642,44 @@ class ResultTest < TinyTds::TestCase end end - it 'calls the provided message handler for each of a series of `print` messages' do + it "calls the provided message handler for each of a series of `print` messages" do messages.clear @client.execute("EXEC tinytds_TestSeveralPrints").do - assert_equal ['hello 1', 'hello 2', 'hello 3'], messages.map { |e| e.message }, 'message list' + assert_equal ["hello 1", "hello 2", "hello 3"], messages.map { |e| e.message }, "message list" end - it 'should flush info messages before raising error in cases of timeout' do - @client = new_connection timeout: 1, message_handler: Proc.new { |m| messages << m } + it "should flush info messages before raising error in cases of timeout" do + @client = new_connection timeout: 1, message_handler: proc { |m| messages << m } action = lambda { @client.execute("print 'hello'; waitfor delay '00:00:02'").do } messages.clear assert_raise_tinytds_error(action) do |e| - assert_match %r{timed out}i, e.message, 'ignore if non-english test run' + assert_match %r{timed out}i, e.message, "ignore if non-english test run" assert_equal 6, e.severity assert_equal 20003, e.db_error_number - assert_equal 'hello', messages.first&.message, 'message text' + assert_equal "hello", messages.first&.message, "message text" end end - it 'should print info messages before raising error in cases of timeout' do - @client = new_connection timeout: 1, message_handler: Proc.new { |m| messages << m } + it "should print info messages before raising error in cases of timeout" do + @client = new_connection timeout: 1, message_handler: proc { |m| messages << m } action = lambda { @client.execute("raiserror('hello', 1, 1) with nowait; waitfor delay '00:00:02'").do } messages.clear assert_raise_tinytds_error(action) do |e| - assert_match %r{timed out}i, e.message, 'ignore if non-english test run' + assert_match %r{timed out}i, e.message, "ignore if non-english test run" assert_equal 6, e.severity assert_equal 20003, e.db_error_number - assert_equal 'hello', messages.first&.message, 'message text' + assert_equal "hello", messages.first&.message, "message text" end end end - it 'must not raise an error when severity is 10 or less' do + it "must not raise an error when severity is 10 or less" do (1..10).to_a.each do |severity| @client.execute("RAISERROR(N'Test #{severity} severity', #{severity}, 1)").do end end - it 'raises an error when severity is greater than 10' do + it "raises an error when severity is greater than 10" do action = lambda { @client.execute("RAISERROR(N'Test 11 severity', 11, 1)").do } assert_raise_tinytds_error(action) do |e| assert_equal "Test 11 severity", e.message @@ -706,7 +694,7 @@ class ResultTest < TinyTds::TestCase def assert_followup_query result = @client.execute(@query1) - assert_equal 1, result.each.first['one'] + assert_equal 1, result.each.first["one"] end def insert_and_select_datatype(datatype) @@ -717,5 +705,4 @@ def insert_and_select_datatype(datatype) flunk "Large #{datatype} data with a length of #{@big_text.length} did not match found text with length of #{found_text.length}" unless @big_text == found_text end end - end diff --git a/test/schema_test.rb b/test/schema_test.rb index a1128d7b..4e8456d5 100644 --- a/test/schema_test.rb +++ b/test/schema_test.rb @@ -1,54 +1,51 @@ -# encoding: utf-8 -require 'test_helper' +require "test_helper" class SchemaTest < TinyTds::TestCase - - describe 'Casting SQL Server schema' do - + describe "Casting SQL Server schema" do before do @@current_schema_loaded ||= load_current_schema @client = new_connection - @gif1px = File.read('test/schema/1px.gif', :mode => "rb:BINARY") + @gif1px = File.read("test/schema/1px.gif", mode: "rb:BINARY") end - it 'casts bigint' do - assert_equal (-9223372036854775807), find_value(11, :bigint) + it "casts bigint" do + assert_equal(-9223372036854775807, find_value(11, :bigint)) assert_equal 9223372036854775806, find_value(12, :bigint) end - it 'casts binary' do + it "casts binary" do value = find_value(21, :binary_50) assert_equal @gif1px + "\000", value assert_binary_encoding(value) end - it 'casts bit' do + it "casts bit" do assert_equal true, find_value(31, :bit) assert_equal false, find_value(32, :bit) assert_nil find_value(21, :bit) end - it 'casts char' do - partial_char = '12345678 ' - assert_equal '1234567890', find_value(41, :char_10) + it "casts char" do + partial_char = "12345678 " + assert_equal "1234567890", find_value(41, :char_10) assert_equal partial_char, find_value(42, :char_10) assert_utf8_encoding find_value(42, :char_10) end - it 'casts datetime' do + it "casts datetime" do # 1753-01-01T00:00:00.000 v = find_value 61, :datetime - assert_instance_of Time, v, 'not in range of Time class' + assert_instance_of Time, v, "not in range of Time class" assert_equal 1753, v.year - assert_equal 01, v.month - assert_equal 01, v.day + assert_equal 0o1, v.month + assert_equal 0o1, v.day assert_equal 0, v.hour assert_equal 0, v.min assert_equal 0, v.sec assert_equal 0, v.usec # 9999-12-31T23:59:59.997 v = find_value 62, :datetime - assert_instance_of Time, v, 'not in range of Time class' + assert_instance_of Time, v, "not in range of Time class" assert_equal 9999, v.year assert_equal 12, v.month assert_equal 31, v.day @@ -56,64 +53,64 @@ class SchemaTest < TinyTds::TestCase assert_equal 59, v.min assert_equal 59, v.sec assert_equal 997000, v.usec - assert_equal utc_offset, find_value(62, :datetime, :timezone => :local).utc_offset - assert_equal 0, find_value(62, :datetime, :timezone => :utc).utc_offset + assert_equal utc_offset, find_value(62, :datetime, timezone: :local).utc_offset + assert_equal 0, find_value(62, :datetime, timezone: :utc).utc_offset # 2010-01-01T12:34:56.123 v = find_value 63, :datetime - assert_instance_of Time, v, 'in range of Time class' + assert_instance_of Time, v, "in range of Time class" assert_equal 2010, v.year - assert_equal 01, v.month - assert_equal 01, v.day + assert_equal 0o1, v.month + assert_equal 0o1, v.day assert_equal 12, v.hour assert_equal 34, v.min assert_equal 56, v.sec assert_equal 123000, v.usec - assert_equal utc_offset, find_value(63, :datetime, :timezone => :local).utc_offset - assert_equal 0, find_value(63, :datetime, :timezone => :utc).utc_offset + assert_equal utc_offset, find_value(63, :datetime, timezone: :local).utc_offset + assert_equal 0, find_value(63, :datetime, timezone: :utc).utc_offset end - it 'casts decimal' do + it "casts decimal" do assert_instance_of BigDecimal, find_value(91, :decimal_9_2) - assert_equal BigDecimal('12345.01'), find_value(91, :decimal_9_2) - assert_equal BigDecimal('1234567.89'), find_value(92, :decimal_9_2) - assert_equal BigDecimal('0.0'), find_value(93, :decimal_16_4) - assert_equal BigDecimal('123456789012.3456'), find_value(94, :decimal_16_4) + assert_equal BigDecimal("12345.01"), find_value(91, :decimal_9_2) + assert_equal BigDecimal("1234567.89"), find_value(92, :decimal_9_2) + assert_equal BigDecimal("0.0"), find_value(93, :decimal_16_4) + assert_equal BigDecimal("123456789012.3456"), find_value(94, :decimal_16_4) end - it 'casts float' do + it "casts float" do assert_equal 123.00000001, find_value(101, :float) assert_equal 0.0, find_value(102, :float) - assert_equal find_value(102, :float).object_id, find_value(102, :float).object_id, 'use global zero float' + assert_equal find_value(102, :float).object_id, find_value(102, :float).object_id, "use global zero float" assert_equal 123.45, find_value(103, :float) end - it 'casts image' do + it "casts image" do value = find_value(141, :image) assert_equal @gif1px, value assert_binary_encoding(value) end - it 'casts int' do - assert_equal (-2147483647), find_value(151, :int) + it "casts int" do + assert_equal(-2147483647, find_value(151, :int)) assert_equal 2147483646, find_value(152, :int) end - it 'casts money' do + it "casts money" do assert_instance_of BigDecimal, find_value(161, :money) - assert_equal BigDecimal('4.20'), find_value(161, :money) - assert_equal BigDecimal('922337203685477.5806'), find_value(163, :money) - assert_equal BigDecimal('-922337203685477.5807'), find_value(162, :money) + assert_equal BigDecimal("4.20"), find_value(161, :money) + assert_equal BigDecimal("922337203685477.5806"), find_value(163, :money) + assert_equal BigDecimal("-922337203685477.5807"), find_value(162, :money) end - it 'casts nchar' do - assert_equal '1234567890', find_value(171, :nchar_10) - assert_equal '123456åå ', find_value(172, :nchar_10) - assert_equal 'abc123 ', find_value(173, :nchar_10) + it "casts nchar" do + assert_equal "1234567890", find_value(171, :nchar_10) + assert_equal "123456åå ", find_value(172, :nchar_10) + assert_equal "abc123 ", find_value(173, :nchar_10) end - it 'casts ntext' do - assert_equal 'test ntext', find_value(181, :ntext) - assert_equal 'test ntext åå', find_value(182, :ntext) + it "casts ntext" do + assert_equal "test ntext", find_value(181, :ntext) + assert_equal "test ntext åå", find_value(182, :ntext) assert_utf8_encoding find_value(182, :ntext) # If this test fails, try setting the "text size" in your freetds.conf. See: http://www.freetds.org/faq.html#textdata large_value = "x" * 5000 @@ -121,284 +118,284 @@ class SchemaTest < TinyTds::TestCase assert_equal large_value, find_value(large_value_id, :ntext) end - it 'casts numeric' do + it "casts numeric" do assert_instance_of BigDecimal, find_value(191, :numeric_18_0) - assert_equal BigDecimal('191'), find_value(191, :numeric_18_0) - assert_equal BigDecimal('123456789012345678'), find_value(192, :numeric_18_0) - assert_equal BigDecimal('12345678901234567890.01'), find_value(193, :numeric_36_2) - assert_equal BigDecimal('123.46'), find_value(194, :numeric_36_2) + assert_equal BigDecimal("191"), find_value(191, :numeric_18_0) + assert_equal BigDecimal("123456789012345678"), find_value(192, :numeric_18_0) + assert_equal BigDecimal("12345678901234567890.01"), find_value(193, :numeric_36_2) + assert_equal BigDecimal("123.46"), find_value(194, :numeric_36_2) end - it 'casts nvarchar' do - assert_equal 'test nvarchar_50', find_value(201, :nvarchar_50) - assert_equal 'test nvarchar_50 åå', find_value(202, :nvarchar_50) + it "casts nvarchar" do + assert_equal "test nvarchar_50", find_value(201, :nvarchar_50) + assert_equal "test nvarchar_50 åå", find_value(202, :nvarchar_50) assert_utf8_encoding find_value(202, :nvarchar_50) end - it 'casts real' do + it "casts real" do assert_in_delta 123.45, find_value(221, :real), 0.01 assert_equal 0.0, find_value(222, :real) - assert_equal find_value(222, :real).object_id, find_value(222, :real).object_id, 'use global zero float' + assert_equal find_value(222, :real).object_id, find_value(222, :real).object_id, "use global zero float" assert_in_delta 0.00001, find_value(223, :real), 0.000001 end - it 'casts smalldatetime' do + it "casts smalldatetime" do # 1901-01-01 15:45:00 v = find_value 231, :smalldatetime assert_instance_of Time, v assert_equal 1901, v.year - assert_equal 01, v.month - assert_equal 01, v.day + assert_equal 0o1, v.month + assert_equal 0o1, v.day assert_equal 15, v.hour assert_equal 45, v.min - assert_equal 00, v.sec - assert_equal Time.local(1901).utc_offset, find_value(231, :smalldatetime, :timezone => :local).utc_offset - assert_equal 0, find_value(231, :smalldatetime, :timezone => :utc).utc_offset + assert_equal 0o0, v.sec + assert_equal Time.local(1901).utc_offset, find_value(231, :smalldatetime, timezone: :local).utc_offset + assert_equal 0, find_value(231, :smalldatetime, timezone: :utc).utc_offset # 2078-06-05 04:20:00 v = find_value 232, :smalldatetime assert_instance_of Time, v assert_equal 2078, v.year - assert_equal 06, v.month - assert_equal 05, v.day - assert_equal 04, v.hour + assert_equal 0o6, v.month + assert_equal 0o5, v.day + assert_equal 0o4, v.hour assert_equal 20, v.min - assert_equal 00, v.sec - assert_equal Time.local(2078, 6).utc_offset, find_value(232, :smalldatetime, :timezone => :local).utc_offset - assert_equal 0, find_value(232, :smalldatetime, :timezone => :utc).utc_offset + assert_equal 0o0, v.sec + assert_equal Time.local(2078, 6).utc_offset, find_value(232, :smalldatetime, timezone: :local).utc_offset + assert_equal 0, find_value(232, :smalldatetime, timezone: :utc).utc_offset end - it 'casts smallint' do - assert_equal (-32767), find_value(241, :smallint) + it "casts smallint" do + assert_equal(-32767, find_value(241, :smallint)) assert_equal 32766, find_value(242, :smallint) end - it 'casts smallmoney' do + it "casts smallmoney" do assert_instance_of BigDecimal, find_value(251, :smallmoney) assert_equal BigDecimal("4.20"), find_value(251, :smallmoney) assert_equal BigDecimal("-214748.3647"), find_value(252, :smallmoney) assert_equal BigDecimal("214748.3646"), find_value(253, :smallmoney) end - it 'casts text' do - assert_equal 'test text', find_value(271, :text) + it "casts text" do + assert_equal "test text", find_value(271, :text) assert_utf8_encoding find_value(271, :text) end - it 'casts tinyint' do + it "casts tinyint" do assert_equal 0, find_value(301, :tinyint) assert_equal 255, find_value(302, :tinyint) end - it 'casts uniqueidentifier' do + it "casts uniqueidentifier" do assert_match %r|\w{8}-\w{4}-\w{4}-\w{4}-\w{12}|, find_value(311, :uniqueidentifier) assert_utf8_encoding find_value(311, :uniqueidentifier) end - it 'casts varbinary' do + it "casts varbinary" do value = find_value(321, :varbinary_50) assert_equal @gif1px, value assert_binary_encoding(value) end - it 'casts varchar' do - assert_equal 'test varchar_50', find_value(341, :varchar_50) + it "casts varchar" do + assert_equal "test varchar_50", find_value(341, :varchar_50) assert_utf8_encoding find_value(341, :varchar_50) end - it 'casts nvarchar(max)' do - assert_equal 'test nvarchar_max', find_value(211, :nvarchar_max) - assert_equal 'test nvarchar_max åå', find_value(212, :nvarchar_max) + it "casts nvarchar(max)" do + assert_equal "test nvarchar_max", find_value(211, :nvarchar_max) + assert_equal "test nvarchar_max åå", find_value(212, :nvarchar_max) assert_utf8_encoding find_value(212, :nvarchar_max) end - it 'casts varbinary(max)' do + it "casts varbinary(max)" do value = find_value(331, :varbinary_max) assert_equal @gif1px, value assert_binary_encoding(value) end - it 'casts varchar(max)' do + it "casts varchar(max)" do value = find_value(351, :varchar_max) - assert_equal 'test varchar_max', value + assert_equal "test varchar_max", value assert_utf8_encoding(value) end - it 'casts xml' do + it "casts xml" do value = find_value(361, :xml) - assert_equal 'batz', value + assert_equal "batz", value assert_utf8_encoding(value) end - it 'casts date' do + it "casts date" do # 0001-01-01 v = find_value 51, :date if @client.tds_73? assert_instance_of Date, v - assert_equal 1, v.year, 'Year' - assert_equal 1, v.month, 'Month' - assert_equal 1, v.day, 'Day' + assert_equal 1, v.year, "Year" + assert_equal 1, v.month, "Month" + assert_equal 1, v.day, "Day" else - assert_equal '0001-01-01', v + assert_equal "0001-01-01", v end # 9999-12-31 v = find_value 52, :date if @client.tds_73? assert_instance_of Date, v - assert_equal 9999, v.year, 'Year' - assert_equal 12, v.month, 'Month' - assert_equal 31, v.day, 'Day' + assert_equal 9999, v.year, "Year" + assert_equal 12, v.month, "Month" + assert_equal 31, v.day, "Day" else - assert_equal '9999-12-31', v + assert_equal "9999-12-31", v end end - it 'casts time' do + it "casts time" do # 15:45:00.709714966 v = find_value 281, :time_2 if @client.tds_73? assert_instance_of Time, v - assert_equal 1900, v.year, 'Year' - assert_equal 1, v.month, 'Month' - assert_equal 1, v.day, 'Day' - assert_equal 15, v.hour, 'Hour' - assert_equal 45, v.min, 'Minute' - assert_equal 0, v.sec, 'Second' - assert_equal 710000, v.usec, 'Microseconds' - assert_equal 710000000, v.nsec, 'Nanoseconds' + assert_equal 1900, v.year, "Year" + assert_equal 1, v.month, "Month" + assert_equal 1, v.day, "Day" + assert_equal 15, v.hour, "Hour" + assert_equal 45, v.min, "Minute" + assert_equal 0, v.sec, "Second" + assert_equal 710000, v.usec, "Microseconds" + assert_equal 710000000, v.nsec, "Nanoseconds" else - assert_equal '15:45:00.71', v + assert_equal "15:45:00.71", v end # 04:20:00.288321545 v = find_value 282, :time_2 if @client.tds_73? assert_instance_of Time, v - assert_equal 1900, v.year, 'Year' - assert_equal 1, v.month, 'Month' - assert_equal 1, v.day, 'Day' - assert_equal 4, v.hour, 'Hour' - assert_equal 20, v.min, 'Minute' - assert_equal 0, v.sec, 'Second' - assert_equal 290000, v.usec, 'Microseconds' - assert_equal 290000000, v.nsec, 'Nanoseconds' + assert_equal 1900, v.year, "Year" + assert_equal 1, v.month, "Month" + assert_equal 1, v.day, "Day" + assert_equal 4, v.hour, "Hour" + assert_equal 20, v.min, "Minute" + assert_equal 0, v.sec, "Second" + assert_equal 290000, v.usec, "Microseconds" + assert_equal 290000000, v.nsec, "Nanoseconds" else - assert_equal '04:20:00.29', v + assert_equal "04:20:00.29", v end # 15:45:00.709714966 v = find_value 283, :time_7 if @client.tds_73? assert_instance_of Time, v - assert_equal 1900, v.year, 'Year' - assert_equal 1, v.month, 'Month' - assert_equal 1, v.day, 'Day' - assert_equal 15, v.hour, 'Hour' - assert_equal 45, v.min, 'Minute' - assert_equal 0, v.sec, 'Second' - assert_equal 709715, v.usec, 'Microseconds' - assert_equal 709715000, v.nsec, 'Nanoseconds' + assert_equal 1900, v.year, "Year" + assert_equal 1, v.month, "Month" + assert_equal 1, v.day, "Day" + assert_equal 15, v.hour, "Hour" + assert_equal 45, v.min, "Minute" + assert_equal 0, v.sec, "Second" + assert_equal 709715, v.usec, "Microseconds" + assert_equal 709715000, v.nsec, "Nanoseconds" else - assert_equal '15:45:00.7097150', v + assert_equal "15:45:00.7097150", v end # 04:20:00.288321545 v = find_value 284, :time_7 if @client.tds_73? assert_instance_of Time, v - assert_equal 1900, v.year, 'Year' - assert_equal 1, v.month, 'Month' - assert_equal 1, v.day, 'Day' - assert_equal 4, v.hour, 'Hour' - assert_equal 20, v.min, 'Minute' - assert_equal 0, v.sec, 'Second' - assert_equal 288321, v.usec, 'Microseconds' - assert_equal 288321500, v.nsec, 'Nanoseconds' + assert_equal 1900, v.year, "Year" + assert_equal 1, v.month, "Month" + assert_equal 1, v.day, "Day" + assert_equal 4, v.hour, "Hour" + assert_equal 20, v.min, "Minute" + assert_equal 0, v.sec, "Second" + assert_equal 288321, v.usec, "Microseconds" + assert_equal 288321500, v.nsec, "Nanoseconds" else - assert_equal '04:20:00.2883215', v + assert_equal "04:20:00.2883215", v end end - it 'casts datetime2' do + it "casts datetime2" do # 0001-01-01 00:00:00.0000000 v = find_value 71, :datetime2_7 if @client.tds_73? assert_instance_of Time, v - assert_equal 1, v.year, 'Year' - assert_equal 1, v.month, 'Month' - assert_equal 1, v.day, 'Day' - assert_equal 0, v.hour, 'Hour' - assert_equal 0, v.min, 'Minute' - assert_equal 0, v.sec, 'Second' - assert_equal 0, v.usec, 'Microseconds' - assert_equal 0, v.nsec, 'Nanoseconds' + assert_equal 1, v.year, "Year" + assert_equal 1, v.month, "Month" + assert_equal 1, v.day, "Day" + assert_equal 0, v.hour, "Hour" + assert_equal 0, v.min, "Minute" + assert_equal 0, v.sec, "Second" + assert_equal 0, v.usec, "Microseconds" + assert_equal 0, v.nsec, "Nanoseconds" else - assert_equal '0001-01-01 00:00:00.0000000', v + assert_equal "0001-01-01 00:00:00.0000000", v end # 1984-01-24 04:20:00.0000000 v = find_value 72, :datetime2_7 if @client.tds_73? assert_instance_of Time, v - assert_equal 1984, v.year, 'Year' - assert_equal 1, v.month, 'Month' - assert_equal 24, v.day, 'Day' - assert_equal 4, v.hour, 'Hour' - assert_equal 20, v.min, 'Minute' - assert_equal 0, v.sec, 'Second' - assert_equal 0, v.usec, 'Microseconds' - assert_equal 0, v.nsec, 'Nanoseconds' + assert_equal 1984, v.year, "Year" + assert_equal 1, v.month, "Month" + assert_equal 24, v.day, "Day" + assert_equal 4, v.hour, "Hour" + assert_equal 20, v.min, "Minute" + assert_equal 0, v.sec, "Second" + assert_equal 0, v.usec, "Microseconds" + assert_equal 0, v.nsec, "Nanoseconds" else - assert_equal '1984-01-24 04:20:00.0000000', v + assert_equal "1984-01-24 04:20:00.0000000", v end # 9999-12-31 23:59:59.9999999 v = find_value 73, :datetime2_7 if @client.tds_73? assert_instance_of Time, v - assert_equal 9999, v.year, 'Year' - assert_equal 12, v.month, 'Month' - assert_equal 31, v.day, 'Day' - assert_equal 23, v.hour, 'Hour' - assert_equal 59, v.min, 'Minute' - assert_equal 59, v.sec, 'Second' - assert_equal 999999, v.usec, 'Microseconds' - assert_equal 999999900, v.nsec, 'Nanoseconds' + assert_equal 9999, v.year, "Year" + assert_equal 12, v.month, "Month" + assert_equal 31, v.day, "Day" + assert_equal 23, v.hour, "Hour" + assert_equal 59, v.min, "Minute" + assert_equal 59, v.sec, "Second" + assert_equal 999999, v.usec, "Microseconds" + assert_equal 999999900, v.nsec, "Nanoseconds" else - assert_equal '9999-12-31 23:59:59.9999999', v + assert_equal "9999-12-31 23:59:59.9999999", v end # 9999-12-31 23:59:59.123456789 v = find_value 74, :datetime2_2 if @client.tds_73? assert_instance_of Time, v - assert_equal 9999, v.year, 'Year' - assert_equal 12, v.month, 'Month' - assert_equal 31, v.day, 'Day' - assert_equal 23, v.hour, 'Hour' - assert_equal 59, v.min, 'Minute' - assert_equal 59, v.sec, 'Second' - assert_equal 120000, v.usec, 'Microseconds' - assert_equal 120000000, v.nsec, 'Nanoseconds' + assert_equal 9999, v.year, "Year" + assert_equal 12, v.month, "Month" + assert_equal 31, v.day, "Day" + assert_equal 23, v.hour, "Hour" + assert_equal 59, v.min, "Minute" + assert_equal 59, v.sec, "Second" + assert_equal 120000, v.usec, "Microseconds" + assert_equal 120000000, v.nsec, "Nanoseconds" else - assert_equal '9999-12-31 23:59:59.12', v + assert_equal "9999-12-31 23:59:59.12", v end end - it 'casts datetimeoffset' do + it "casts datetimeoffset" do # 1984-01-24T04:20:00.1234567-08:00 v = find_value 84, :datetimeoffset_7 if @client.tds_73? assertions = lambda { assert_instance_of Time, v - assert_equal 1984, v.year, 'Year' - assert_equal 1, v.month, 'Month' - assert_equal 24, v.day, 'Day' - assert_equal 4, v.hour, 'Hour' - assert_equal 20, v.min, 'Minute' - assert_equal 59, v.sec, 'Second' - assert_equal 123456, v.usec, 'Microseconds' - assert_equal 123456700, v.nsec, 'Nanoseconds' - assert_equal (-28800), v.utc_offset, 'Offset' + assert_equal 1984, v.year, "Year" + assert_equal 1, v.month, "Month" + assert_equal 24, v.day, "Day" + assert_equal 4, v.hour, "Hour" + assert_equal 20, v.min, "Minute" + assert_equal 59, v.sec, "Second" + assert_equal 123456, v.usec, "Microseconds" + assert_equal 123456700, v.nsec, "Nanoseconds" + assert_equal(-28800, v.utc_offset, "Offset") } assertions.call v = find_value 84, :datetimeoffset_7, timezone: :local assertions.call # Ignores timezone query option. else - assert_equal '1984-01-24 04:20:59.1234567 -08:00', v + assert_equal "1984-01-24 04:20:59.1234567 -08:00", v end end @@ -416,6 +413,5 @@ class SchemaTest < TinyTds::TestCase # value = find_value 131, :hierarchyid # assert_equal '', value # end - end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 640d8c0c..f5ac46d3 100755 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,26 +1,24 @@ -# encoding: UTF-8 -require 'bundler' ; Bundler.require :development, :test -require 'tiny_tds' -require 'minitest/autorun' -require 'toxiproxy' +require "bundler" +Bundler.require :development, :test +require "tiny_tds" +require "minitest/autorun" +require "toxiproxy" require "minitest/reporters" Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new, Minitest::Reporters::JUnitReporter.new] -TINYTDS_SCHEMAS = ['sqlserver_2017', 'sqlserver_azure'].freeze +TINYTDS_SCHEMAS = ["sqlserver_2017", "sqlserver_azure"].freeze module TinyTds class TestCase < Minitest::Spec - class << self - def current_schema - ENV['TINYTDS_SCHEMA'] || 'sqlserver_2017' + ENV["TINYTDS_SCHEMA"] || "sqlserver_2017" end TINYTDS_SCHEMAS.each do |schema| - define_method "#{schema}?" do - schema == self.current_schema + define_method :"#{schema}?" do + schema == current_schema end end end @@ -30,7 +28,7 @@ def current_schema protected TINYTDS_SCHEMAS.each do |schema| - define_method "#{schema}?" do + define_method :"#{schema}?" do schema == self.class.current_schema end end @@ -39,45 +37,44 @@ def current_schema self.class.current_schema end - def close_client(client=@client) + def close_client(client = @client) client.close if defined?(client) && client.is_a?(TinyTds::Client) end - def new_connection(options={}) + def new_connection(options = {}) client = TinyTds::Client.new(connection_options(options)) if sqlserver_azure? - client.execute('SET ANSI_NULLS ON').do - client.execute('SET CURSOR_CLOSE_ON_COMMIT OFF').do - client.execute('SET ANSI_NULL_DFLT_ON ON').do - client.execute('SET IMPLICIT_TRANSACTIONS OFF').do - client.execute('SET ANSI_PADDING ON').do - client.execute('SET QUOTED_IDENTIFIER ON').do - client.execute('SET ANSI_WARNINGS ON').do + client.execute("SET ANSI_NULLS ON").do + client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do + client.execute("SET ANSI_NULL_DFLT_ON ON").do + client.execute("SET IMPLICIT_TRANSACTIONS OFF").do + client.execute("SET ANSI_PADDING ON").do + client.execute("SET QUOTED_IDENTIFIER ON").do + client.execute("SET ANSI_WARNINGS ON").do else - client.execute('SET ANSI_DEFAULTS ON').do - client.execute('SET CURSOR_CLOSE_ON_COMMIT OFF').do - client.execute('SET IMPLICIT_TRANSACTIONS OFF').do + client.execute("SET ANSI_DEFAULTS ON").do + client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do + client.execute("SET IMPLICIT_TRANSACTIONS OFF").do end - client.execute('SET TEXTSIZE 2147483647').do - client.execute('SET CONCAT_NULL_YIELDS_NULL ON').do + client.execute("SET TEXTSIZE 2147483647").do + client.execute("SET CONCAT_NULL_YIELDS_NULL ON").do client end - def connection_options(options={}) - username = (sqlserver_azure? ? ENV['TINYTDS_UNIT_AZURE_USER'] : ENV['TINYTDS_UNIT_USER']) || 'tinytds' - password = (sqlserver_azure? ? ENV['TINYTDS_UNIT_AZURE_PASS'] : ENV['TINYTDS_UNIT_PASS']) || '' - { :dataserver => sqlserver_azure? ? nil : ENV['TINYTDS_UNIT_DATASERVER'], - :host => ENV['TINYTDS_UNIT_HOST'] || 'localhost', - :port => ENV['TINYTDS_UNIT_PORT'] || '1433', - :tds_version => ENV['TINYTDS_UNIT_VERSION'], - :username => username, - :password => password, - :database => ENV['TINYTDS_UNIT_DATABASE'] || 'tinytdstest', - :appname => 'TinyTds Dev', - :login_timeout => 5, - :timeout => connection_timeout, - :azure => sqlserver_azure? - }.merge(options) + def connection_options(options = {}) + username = (sqlserver_azure? ? ENV["TINYTDS_UNIT_AZURE_USER"] : ENV["TINYTDS_UNIT_USER"]) || "tinytds" + password = (sqlserver_azure? ? ENV["TINYTDS_UNIT_AZURE_PASS"] : ENV["TINYTDS_UNIT_PASS"]) || "" + {dataserver: sqlserver_azure? ? nil : ENV["TINYTDS_UNIT_DATASERVER"], + host: ENV["TINYTDS_UNIT_HOST"] || "localhost", + port: ENV["TINYTDS_UNIT_PORT"] || "1433", + tds_version: ENV["TINYTDS_UNIT_VERSION"], + username: username, + password: password, + database: ENV["TINYTDS_UNIT_DATABASE"] || "tinytdstest", + appname: "TinyTds Dev", + login_timeout: 5, + timeout: connection_timeout, + azure: sqlserver_azure?}.merge(options) end def connection_timeout @@ -85,7 +82,7 @@ def connection_timeout end def assert_client_works(client) - _(client.execute("SELECT 'client_works' as [client_works]").each).must_equal [{'client_works' => 'client_works'}] + _(client.execute("SELECT 'client_works' as [client_works]").each).must_equal [{"client_works" => "client_works"}] end def assert_new_connections_work @@ -102,28 +99,26 @@ def assert_raise_tinytds_error(action) rescue TinyTds::Error => e error_raised = true end - assert error_raised, 'expected a TinyTds::Error but none happened' + assert error_raised, "expected a TinyTds::Error but none happened" yield e ensure close_client(result) end def inspect_tinytds_exception - begin - yield - rescue TinyTds::Error => e - props = { :source => e.source, :message => e.message, :severity => e.severity, - :db_error_number => e.db_error_number, :os_error_number => e.os_error_number } - raise "TinyTds::Error - #{props.inspect}" - end + yield + rescue TinyTds::Error => e + props = {source: e.source, message: e.message, severity: e.severity, + db_error_number: e.db_error_number, os_error_number: e.os_error_number} + raise "TinyTds::Error - #{props.inspect}" end def assert_binary_encoding(value) - assert_equal Encoding.find('BINARY'), value.encoding + assert_equal Encoding.find("BINARY"), value.encoding end def assert_utf8_encoding(value) - assert_equal Encoding.find('UTF-8'), value.encoding + assert_equal Encoding.find("UTF-8"), value.encoding end def rubyRbx? @@ -131,17 +126,17 @@ def rubyRbx? end def ruby_windows? - RbConfig::CONFIG['host_os'] =~ /ming/ + RbConfig::CONFIG["host_os"] =~ /ming/ end def ruby_darwin? - RbConfig::CONFIG['host_os'] =~ /darwin/ + RbConfig::CONFIG["host_os"] =~ /darwin/ end def load_current_schema loader = new_connection - schema_file = File.expand_path File.join(File.dirname(__FILE__), 'schema', "#{current_schema}.sql") - schema_sql = File.open(schema_file,"rb:UTF-8") { |f|f.read } + schema_file = File.expand_path File.join(File.dirname(__FILE__), "schema", "#{current_schema}.sql") + schema_sql = File.open(schema_file, "rb:UTF-8") { |f| f.read } loader.execute(drop_sql).do loader.execute(schema_sql).do loader.execute(sp_sql).do @@ -188,14 +183,14 @@ def sp_error_sql end def sp_several_prints_sql - %|CREATE PROCEDURE tinytds_TestSeveralPrints + %(CREATE PROCEDURE tinytds_TestSeveralPrints AS PRINT 'hello 1' PRINT 'hello 2' - PRINT 'hello 3'| + PRINT 'hello 3') end - def find_value(id, column, query_options={}) + def find_value(id, column, query_options = {}) query_options[:timezone] ||= :utc sql = "SELECT [#{column}] FROM [datatypes] WHERE [id] = #{id}" @client.execute(sql).each(query_options).first[column.to_s] @@ -223,19 +218,19 @@ def init_toxiproxy # docker-compose.yml handles this automatically for us. In instances where someone is using their own local mssql container they'll # need to set up the networks manually and set TINYTDS_UNIT_HOST to their mssql container name # For anything other than localhost just use the environment config - toxi_host = ENV['TOXIPROXY_HOST'] || 'localhost' + toxi_host = ENV["TOXIPROXY_HOST"] || "localhost" toxi_api_port = 8474 toxi_test_port = 1234 Toxiproxy.host = "http://#{toxi_host}:#{toxi_api_port}" - toxi_upstream_host = ENV['TINYTDS_UNIT_HOST_TEST'] || ENV['TINYTDS_UNIT_HOST'] || 'localhost' - toxi_upstream_port = ENV['TINYTDS_UNIT_PORT'] || 1433 + toxi_upstream_host = ENV["TINYTDS_UNIT_HOST_TEST"] || ENV["TINYTDS_UNIT_HOST"] || "localhost" + toxi_upstream_port = ENV["TINYTDS_UNIT_PORT"] || 1433 puts "\n-------------------------" puts "Toxiproxy api listener: #{toxi_host}:#{toxi_api_port}" puts "Toxiproxy unit test listener: #{toxi_host}:#{toxi_test_port}" puts "Toxiproxy upstream sqlserver: #{toxi_upstream_host}:#{toxi_upstream_port}" - puts '-------------------------' + puts "-------------------------" Toxiproxy.populate([ { diff --git a/test/thread_test.rb b/test/thread_test.rb index a79353f2..4fe1bad6 100644 --- a/test/thread_test.rb +++ b/test/thread_test.rb @@ -1,25 +1,23 @@ -require 'test_helper' -require 'logger' -require 'benchmark' +require "test_helper" +require "logger" +require "benchmark" class ThreadTest < TinyTds::TestCase - - describe 'Threaded SELECT queries' do - + describe "Threaded SELECT queries" do before do @logger = Logger.new $stdout @logger.level = Logger::WARN @poolsize = 4 @numthreads = 10 @query = "waitfor delay '00:00:01'" - @pool = ConnectionPool.new(:size => @poolsize, :timeout => 5) { new_connection } + @pool = ConnectionPool.new(size: @poolsize, timeout: 5) { new_connection } end after do @pool.shutdown { |c| c.close } end - it 'should finish faster in parallel' do + it "should finish faster in parallel" do skip if sqlserver_azure? x = Benchmark.realtime do threads = [] @@ -35,24 +33,22 @@ class ThreadTest < TinyTds::TestCase threads.each { |t| t.join } end assert x < @numthreads, "#{x} is not faster than #{@numthreads} seconds" - mintime = (1.0*@numthreads/@poolsize).ceil + mintime = (1.0 * @numthreads / @poolsize).ceil @logger.info "#{@numthreads} queries on #{@poolsize} threads: #{x} sec. Minimum time: #{mintime} sec." assert x > mintime, "#{x} is not slower than #{mintime} seconds" end - it 'should not crash on error in parallel' do + it "should not crash on error in parallel" do skip if sqlserver_azure? threads = [] @numthreads.times do |i| threads << Thread.new do @pool.with do |client| - begin - result = client.execute "select dbname()" - result.each { |r| puts r } - rescue Exception => _e - # We are throwing an error on purpose here since 0.6.1 would - # segfault on errors thrown in threads - end + result = client.execute "select dbname()" + result.each { |r| puts r } + rescue => _e + # We are throwing an error on purpose here since 0.6.1 would + # segfault on errors thrown in threads end end end @@ -60,27 +56,25 @@ class ThreadTest < TinyTds::TestCase assert true end - it 'should cancel when hitting timeout in thread' do + it "should cancel when hitting timeout in thread" do exception = false thread = Thread.new do @pool.with do |client| - begin - delay = ('0' + (connection_timeout + 2).to_s)[-2,2] # Two seconds longer than default. - result = client.execute "waitfor delay '00:00:#{delay}'; select db_name()" - result.each { |r| puts r } - rescue TinyTds::Error => e - if e.message == 'Adaptive Server connection timed out' - exception = true - end + delay = ("0" + (connection_timeout + 2).to_s)[-2, 2] # Two seconds longer than default. + result = client.execute "waitfor delay '00:00:#{delay}'; select db_name()" + result.each { |r| puts r } + rescue TinyTds::Error => e + if e.message == "Adaptive Server connection timed out" + exception = true end end end timer_thread = Thread.new do # Sleep until after the timeout should have been reached - sleep(connection_timeout+2) - if not exception + sleep(connection_timeout + 2) + if !exception thread.kill raise "Timeout passed without query timing out" end @@ -91,8 +85,5 @@ class ThreadTest < TinyTds::TestCase assert exception end - end - end - diff --git a/tiny_tds.gemspec b/tiny_tds.gemspec index 67f5e903..8b427e99 100644 --- a/tiny_tds.gemspec +++ b/tiny_tds.gemspec @@ -1,32 +1,31 @@ -# -*- encoding: utf-8 -*- -$LOAD_PATH.push File.expand_path('../lib', __FILE__) -require 'tiny_tds/version' +$LOAD_PATH.push File.expand_path("../lib", __FILE__) +require "tiny_tds/version" Gem::Specification.new do |s| - s.name = 'tiny_tds' - s.version = TinyTds::VERSION - s.platform = Gem::Platform::RUBY - s.authors = ['Ken Collins', 'Erik Bryn', 'Will Bond'] - s.email = ['ken@metaskills.net', 'will@wbond.net'] - s.homepage = 'http://github.com/rails-sqlserver/tiny_tds' - s.summary = 'TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library.' - s.description = 'TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library. Developed for the ActiveRecord SQL Server adapter.' - s.files = `git ls-files`.split("\n") + Dir.glob('exe/*') - s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") - s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } - s.require_paths = ['lib'] - s.rdoc_options = ['--charset=UTF-8'] - s.extensions = ['ext/tiny_tds/extconf.rb'] - s.license = 'MIT' - s.required_ruby_version = '>= 2.7.0' - s.metadata['msys2_mingw_dependencies'] = 'freetds' - s.add_dependency 'bigdecimal', '~> 3' - s.add_development_dependency 'mini_portile2', '~> 2.8.0' - s.add_development_dependency 'rake', '~> 13.0.0' - s.add_development_dependency 'rake-compiler', '~> 1.2' - s.add_development_dependency 'rake-compiler-dock', '~> 1.7.0' - s.add_development_dependency 'minitest', '~> 5.25' - s.add_development_dependency 'minitest-reporters', '~> 1.6.1' - s.add_development_dependency 'connection_pool', '~> 2.2.0' - s.add_development_dependency 'toxiproxy', '~> 2.0.0' + s.name = "tiny_tds" + s.version = TinyTds::VERSION + s.platform = Gem::Platform::RUBY + s.authors = ["Ken Collins", "Erik Bryn", "Will Bond"] + s.email = ["ken@metaskills.net", "will@wbond.net"] + s.homepage = "http://github.com/rails-sqlserver/tiny_tds" + s.summary = "TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library." + s.description = "TinyTDS - A modern, simple and fast FreeTDS library for Ruby using DB-Library. Developed for the ActiveRecord SQL Server adapter." + s.files = `git ls-files`.split("\n") + Dir.glob("exe/*") + s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } + s.require_paths = ["lib"] + s.rdoc_options = ["--charset=UTF-8"] + s.extensions = ["ext/tiny_tds/extconf.rb"] + s.license = "MIT" + s.required_ruby_version = ">= 2.7.0" + s.metadata["msys2_mingw_dependencies"] = "freetds" + s.add_dependency "bigdecimal", "~> 3" + s.add_development_dependency "mini_portile2", "~> 2.8.0" + s.add_development_dependency "rake", "~> 13.0.0" + s.add_development_dependency "rake-compiler", "~> 1.2" + s.add_development_dependency "rake-compiler-dock", "~> 1.7.0" + s.add_development_dependency "minitest", "~> 5.25" + s.add_development_dependency "minitest-reporters", "~> 1.6.1" + s.add_development_dependency "connection_pool", "~> 2.2.0" + s.add_development_dependency "toxiproxy", "~> 2.0.0" + s.add_development_dependency "standard", "~> 1.31.0" end