class Sequel::TinyTDS::Database
Public Instance Methods
Transfer the :user option to the :username option.
# File lib/sequel/adapters/tinytds.rb 13 def connect(server) 14 opts = server_opts(server) 15 opts[:username] = opts[:user] 16 c = TinyTds::Client.new(opts) 17 c.query_options.merge!(:cache_rows=>false) 18 19 if (ts = opts[:textsize]) 20 sql = "SET TEXTSIZE #{typecast_value_integer(ts)}" 21 log_connection_yield(sql, c){c.execute(sql)} 22 end 23 24 c 25 end
Execute the given sql
on the server. If the :return option is present, its value should be a method symbol that is called on the TinyTds::Result object returned from executing the sql
. The value of such a method is returned to the caller. Otherwise, if a block is given, it is yielded the result object. If no block is given and a :return is not present, nil
is returned.
# File lib/sequel/adapters/tinytds.rb 33 def execute(sql, opts=OPTS) 34 synchronize(opts[:server]) do |c| 35 begin 36 m = opts[:return] 37 r = nil 38 if (args = opts[:arguments]) && !args.empty? 39 types = [] 40 values = [] 41 args.each_with_index do |(k, v), i| 42 v, type = ps_arg_type(v) 43 types << "@#{k} #{type}" 44 values << "@#{k} = #{v}" 45 end 46 case m 47 when :do 48 sql = "#{sql}; SELECT @@ROWCOUNT AS AffectedRows" 49 single_value = true 50 when :insert 51 sql = "#{sql}; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident" 52 single_value = true 53 end 54 sql = "EXEC sp_executesql N'#{c.escape(sql)}', N'#{c.escape(types.join(', '))}', #{values.join(', ')}" 55 log_connection_yield(sql, c) do 56 r = c.execute(sql) 57 r.each{|row| return row.values.first} if single_value 58 end 59 else 60 log_connection_yield(sql, c) do 61 r = c.execute(sql) 62 return r.public_send(m) if m 63 end 64 end 65 yield(r) if block_given? 66 rescue TinyTds::Error => e 67 raise_error(e, :disconnect=>!c.active?) 68 ensure 69 r.cancel if r && c.sqlsent? && c.active? 70 end 71 end 72 end
# File lib/sequel/adapters/tinytds.rb 86 def execute_ddl(sql, opts=OPTS) 87 opts = Hash[opts] 88 opts[:return] = :each 89 execute(sql, opts) 90 nil 91 end
# File lib/sequel/adapters/tinytds.rb 74 def execute_dui(sql, opts=OPTS) 75 opts = Hash[opts] 76 opts[:return] = :do 77 execute(sql, opts) 78 end
# File lib/sequel/adapters/tinytds.rb 80 def execute_insert(sql, opts=OPTS) 81 opts = Hash[opts] 82 opts[:return] = :insert 83 execute(sql, opts) 84 end
Private Instance Methods
Choose whether to use unicode strings on initialization
# File lib/sequel/adapters/tinytds.rb 96 def adapter_initialize 97 set_mssql_unicode_strings 98 end
For some reason, unless you specify a column can be NULL, it assumes NOT NULL, so turn NULL on by default unless the column is a primary key column.
Sequel::Database#column_list_sql
# File lib/sequel/adapters/tinytds.rb 103 def column_list_sql(g) 104 pks = [] 105 g.constraints.each{|c| pks = c[:columns] if c[:type] == :primary_key} 106 g.columns.each{|c| c[:null] = true if !pks.include?(c[:name]) && !c[:primary_key] && !c.has_key?(:null) && !c.has_key?(:allow_null)} 107 super 108 end
tiny_tds uses TinyTds::Error as the base error class.
# File lib/sequel/adapters/tinytds.rb 111 def database_error_classes 112 [TinyTds::Error] 113 end
Stupid MSSQL
maps foreign key and check constraint violations to the same error code, and doesn't expose the sqlstate. Use database error numbers if present and unambiguous, otherwise fallback to the regexp mapping.
Sequel::Database#database_specific_error_class
# File lib/sequel/adapters/tinytds.rb 119 def database_specific_error_class(exception, opts) 120 case exception.db_error_number 121 when 515 122 NotNullConstraintViolation 123 when 2627 124 UniqueConstraintViolation 125 else 126 super 127 end 128 end
# File lib/sequel/adapters/tinytds.rb 130 def dataset_class_default 131 Dataset 132 end
Return true if the :conn argument is present and not active.
Sequel::Database#disconnect_error?
# File lib/sequel/adapters/tinytds.rb 135 def disconnect_error?(e, opts) 136 super || (opts[:conn] && !opts[:conn].active?) || ((e.is_a?(::TinyTds::Error) && /\A(Attempt to initiate a new Adaptive Server operation with results pending|The request failed to run because the batch is aborted, this can be caused by abort signal sent from client|Adaptive Server connection timed out)/.match(e.message))) 137 end
Dispose of any possible results of execution.
# File lib/sequel/adapters/tinytds.rb 140 def log_connection_execute(conn, sql) 141 log_connection_yield(sql, conn){conn.execute(sql).each} 142 end
Return a 2 element array with the literal value and type to use in the prepared statement call for the given value and connection.
# File lib/sequel/adapters/tinytds.rb 146 def ps_arg_type(v) 147 case v 148 when Integer 149 [v, 'bigint'] 150 when Float 151 [v, 'double precision'] 152 when Numeric 153 [v, 'numeric'] 154 when Time 155 if v.is_a?(SQLTime) 156 [literal(v), 'time'] 157 else 158 [literal(v), 'datetime'] 159 end 160 when DateTime 161 [literal(v), 'datetime'] 162 when Date 163 [literal(v), 'date'] 164 when nil 165 ['NULL', 'nvarchar(max)'] 166 when true 167 ['1', 'int'] 168 when false 169 ['0', 'int'] 170 when SQL::Blob 171 [literal(v), 'varbinary(max)'] 172 else 173 [literal(v), 'nvarchar(max)'] 174 end 175 end