class Sequel::TinyTDS::Database

Constants

DatasetClass
TINYTDS_DISCONNECT_ERRORS

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 (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 33
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.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

Execute the DDL sql on the database and return nil.

# File lib/sequel/adapters/tinytds.rb, line 90
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

Return the number of rows modified by the given sql.

# File lib/sequel/adapters/tinytds.rb, line 75
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

Return the value of the autogenerated primary key (if any) for the row inserted by the given sql.

# File lib/sequel/adapters/tinytds.rb, line 83
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 100
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 107
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 115
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 123
def database_specific_error_class(exception, opts)
  case exception.db_error_number
  when 515
    NotNullConstraintViolation
  when 2627
    UniqueConstraintViolation
  else
    super
  end
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 136
def disconnect_error?(e, opts)
  super || (opts[:conn] && !opts[:conn].active?) || ((e.is_a?(::TinyTds::Error) && TINYTDS_DISCONNECT_ERRORS.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 141
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 147
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