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 opts[:ansi] 20 sql = %w( 21 ANSI_NULLS 22 ANSI_PADDING 23 ANSI_WARNINGS 24 ANSI_NULL_DFLT_ON 25 QUOTED_IDENTIFIER 26 CONCAT_NULL_YIELDS_NULL 27 ).map{|v| "SET #{v} ON"}.join(";") 28 log_connection_yield(sql, c){c.execute(sql)} 29 end 30 31 if (ts = opts[:textsize]) 32 sql = "SET TEXTSIZE #{typecast_value_integer(ts)}" 33 log_connection_yield(sql, c){c.execute(sql)} 34 end 35 36 c 37 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 45 def execute(sql, opts=OPTS) 46 synchronize(opts[:server]) do |c| 47 begin 48 m = opts[:return] 49 r = nil 50 if (args = opts[:arguments]) && !args.empty? 51 types = [] 52 values = [] 53 args.each_with_index do |(k, v), i| 54 v, type = ps_arg_type(v) 55 types << "@#{k} #{type}" 56 values << "@#{k} = #{v}" 57 end 58 case m 59 when :do 60 sql = "#{sql}; SELECT @@ROWCOUNT AS AffectedRows" 61 single_value = true 62 when :insert 63 sql = "#{sql}; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident" 64 single_value = true 65 end 66 sql = "EXEC sp_executesql N'#{c.escape(sql)}', N'#{c.escape(types.join(', '))}', #{values.join(', ')}" 67 log_connection_yield(sql, c) do 68 r = c.execute(sql) 69 r.each{|row| return row.values.first} if single_value 70 end 71 else 72 log_connection_yield(sql, c) do 73 r = c.execute(sql) 74 return r.public_send(m) if m 75 end 76 end 77 yield(r) if block_given? 78 rescue TinyTds::Error => e 79 raise_error(e, :disconnect=>!c.active?) 80 ensure 81 r.cancel if r && c.sqlsent? && c.active? 82 end 83 end 84 end
# File lib/sequel/adapters/tinytds.rb 98 def execute_ddl(sql, opts=OPTS) 99 opts = Hash[opts] 100 opts[:return] = :each 101 execute(sql, opts) 102 nil 103 end
# File lib/sequel/adapters/tinytds.rb 86 def execute_dui(sql, opts=OPTS) 87 opts = Hash[opts] 88 opts[:return] = :do 89 execute(sql, opts) 90 end
# File lib/sequel/adapters/tinytds.rb 92 def execute_insert(sql, opts=OPTS) 93 opts = Hash[opts] 94 opts[:return] = :insert 95 execute(sql, opts) 96 end
Private Instance Methods
Choose whether to use unicode strings on initialization
# File lib/sequel/adapters/tinytds.rb 108 def adapter_initialize 109 set_mssql_unicode_strings 110 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 115 def column_list_sql(g) 116 pks = [] 117 g.constraints.each{|c| pks = c[:columns] if c[:type] == :primary_key} 118 g.columns.each{|c| c[:null] = true if !pks.include?(c[:name]) && !c[:primary_key] && !c.has_key?(:null) && !c.has_key?(:allow_null)} 119 super 120 end
tiny_tds uses TinyTds::Error as the base error class.
# File lib/sequel/adapters/tinytds.rb 123 def database_error_classes 124 [TinyTds::Error] 125 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 131 def database_specific_error_class(exception, opts) 132 case exception.db_error_number 133 when 515 134 NotNullConstraintViolation 135 when 2627 136 UniqueConstraintViolation 137 else 138 super 139 end 140 end
# File lib/sequel/adapters/tinytds.rb 142 def dataset_class_default 143 Dataset 144 end
Return true if the :conn argument is present and not active.
Sequel::Database#disconnect_error?
# File lib/sequel/adapters/tinytds.rb 147 def disconnect_error?(e, opts) 148 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))) 149 end
Dispose of any possible results of execution.
# File lib/sequel/adapters/tinytds.rb 152 def log_connection_execute(conn, sql) 153 log_connection_yield(sql, conn){conn.execute(sql).each} 154 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 158 def ps_arg_type(v) 159 case v 160 when Integer 161 [v, 'bigint'] 162 when Float 163 [v, 'double precision'] 164 when Numeric 165 [v, 'numeric'] 166 when Time 167 if v.is_a?(SQLTime) 168 [literal(v), 'time'] 169 else 170 [literal(v), 'datetime'] 171 end 172 when DateTime 173 [literal(v), 'datetime'] 174 when Date 175 [literal(v), 'date'] 176 when nil 177 ['NULL', 'nvarchar(max)'] 178 when true 179 ['1', 'int'] 180 when false 181 ['0', 'int'] 182 when SQL::Blob 183 [literal(v), 'varbinary(max)'] 184 else 185 [literal(v), 'nvarchar(max)'] 186 end 187 end