class Sequel::TinyTDS::Database

Public Instance Methods

connect(server) click to toggle source

Transfer the :user option to the :username option.

# File lib/sequel/adapters/tinytds.rb, line 13
def connect(server)
  opts = server_opts(server)
  opts[:username] = opts[:user]
  c = TinyTds::Client.new(opts)
  c.query_options.merge!(:cache_rows=>false)

  if opts[:ansi]
    sql = %w(
      ANSI_NULLS
      ANSI_PADDING
      ANSI_WARNINGS
      ANSI_NULL_DFLT_ON
      QUOTED_IDENTIFIER
      CONCAT_NULL_YIELDS_NULL
    ).map{|v| "SET #{v} ON"}.join(";")
    log_connection_yield(sql, c){c.execute(sql)}
  end

  if (ts = opts[:textsize])
    sql = "SET TEXTSIZE #{typecast_value_integer(ts)}"
    log_connection_yield(sql, c){c.execute(sql)}
  end

  c
end
execute(sql, opts=OPTS) { |r| ... } click to toggle source

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, line 45
def execute(sql, opts=OPTS)
  synchronize(opts[:server]) do |c|
    begin
      m = opts[:return]
      r = nil
      if (args = opts[:arguments]) && !args.empty?
        types = []
        values = []
        args.each_with_index do |(k, v), i|
          v, type = ps_arg_type(v)
          types << "@#{k} #{type}"
          values << "@#{k} = #{v}"
        end
        case m
        when :do
          sql = "#{sql}; SELECT @@ROWCOUNT AS AffectedRows"
          single_value = true
        when :insert
          sql = "#{sql}; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident"
          single_value = true
        end
        sql = "EXEC sp_executesql N'#{c.escape(sql)}', N'#{c.escape(types.join(', '))}', #{values.join(', ')}"
        log_connection_yield(sql, c) do
          r = c.execute(sql)
          r.each{|row| return row.values.first} if single_value
        end
      else
        log_connection_yield(sql, c) do
          r = c.execute(sql)
          return r.public_send(m) if m
        end
      end
      yield(r) if block_given?
    rescue TinyTds::Error => e
      raise_error(e, :disconnect=>!c.active?)
    ensure
      r.cancel if r && c.sqlsent? && c.active?
    end
  end
end
execute_ddl(sql, opts=OPTS) click to toggle source
# File lib/sequel/adapters/tinytds.rb, line 98
def execute_ddl(sql, opts=OPTS)
  opts = Hash[opts]
  opts[:return] = :each
  execute(sql, opts)
  nil
end
execute_dui(sql, opts=OPTS) click to toggle source
# File lib/sequel/adapters/tinytds.rb, line 86
def execute_dui(sql, opts=OPTS)
  opts = Hash[opts]
  opts[:return] = :do
  execute(sql, opts)
end
execute_insert(sql, opts=OPTS) click to toggle source
# File lib/sequel/adapters/tinytds.rb, line 92
def execute_insert(sql, opts=OPTS)
  opts = Hash[opts]
  opts[:return] = :insert
  execute(sql, opts)
end

Private Instance Methods

adapter_initialize() click to toggle source

Choose whether to use unicode strings on initialization

# File lib/sequel/adapters/tinytds.rb, line 108
def adapter_initialize
  set_mssql_unicode_strings
end
column_list_sql(g) click to toggle source

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.

Calls superclass method Sequel::Database#column_list_sql
# File lib/sequel/adapters/tinytds.rb, line 115
def column_list_sql(g)
  pks = []
  g.constraints.each{|c| pks = c[:columns] if c[:type] == :primary_key} 
  g.columns.each{|c| c[:null] = true if !pks.include?(c[:name]) && !c[:primary_key] && !c.has_key?(:null) && !c.has_key?(:allow_null)}
  super
end
database_error_classes() click to toggle source

tiny_tds uses TinyTds::Error as the base error class.

# File lib/sequel/adapters/tinytds.rb, line 123
def database_error_classes
  [TinyTds::Error]
end
database_specific_error_class(exception, opts) click to toggle source

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.

# File lib/sequel/adapters/tinytds.rb, line 131
def database_specific_error_class(exception, opts)
  case exception.db_error_number
  when 515
    NotNullConstraintViolation
  when 2627
    UniqueConstraintViolation
  else
    super
  end
end
dataset_class_default() click to toggle source
# File lib/sequel/adapters/tinytds.rb, line 142
def dataset_class_default
  Dataset
end
disconnect_error?(e, opts) click to toggle source

Return true if the :conn argument is present and not active.

Calls superclass method Sequel::Database#disconnect_error?
# File lib/sequel/adapters/tinytds.rb, line 147
def disconnect_error?(e, opts)
  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)))
end
log_connection_execute(conn, sql) click to toggle source

Dispose of any possible results of execution.

# File lib/sequel/adapters/tinytds.rb, line 152
def log_connection_execute(conn, sql)
  log_connection_yield(sql, conn){conn.execute(sql).each}
end
ps_arg_type(v) click to toggle source

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, line 158
def ps_arg_type(v)
  case v
  when Integer
    [v, 'bigint']
  when Float
    [v, 'double precision']
  when Numeric
    [v, 'numeric']
  when Time
    if v.is_a?(SQLTime)
      [literal(v), 'time']
    else
      [literal(v), 'datetime']
    end
  when DateTime
    [literal(v), 'datetime']
  when Date
    [literal(v), 'date']
  when nil
    ['NULL', 'nvarchar(max)']
  when true
    ['1', 'int']
  when false
    ['0', 'int']
  when SQL::Blob
    [literal(v), 'varbinary(max)']
  else
    [literal(v), 'nvarchar(max)']
  end
end