module Sequel::Model::ClassMethods

def Model(source)

end
dataset # => DB1[:comments]
class Comment < Sequel::Model(DB1)
# Using a database

end
dataset # => DB1[:something]
class Comment < Sequel::Model(DB1[:something])
# Using a dataset

end
table_name # => :something
class Comment < Sequel::Model(:something)
# Using a symbol

called on Sequel itself, using Sequel::Model(:something).
When creating subclasses of Sequel::Model itself, this method is usually

name that Sequel would use.
for a model class, if the table name doesn't match the default table
The purpose of this method is to set the dataset/database automatically

classes in order to create the dataset.
class will use the default database for model
other :: Sets the table name for this model to +source+. The
Dataset :: Sets the dataset for this model to +source+.
dataset to use)
with the +Database+ in +source+ to create the
subclass sets the table name (which is combined
from the returned class, where the name of the
Generally only useful when subclassing directly
Database :: Sets the database for this model to +source+.

+source+ should be an instance of one of the following classes:
Lets you create a Model subclass with its dataset already set.
def Model(source)
  if cache_anonymous_models
    cache = Sequel.synchronize{@Model_cache ||= {}}
    if klass = Sequel.synchronize{cache[source]}
      return klass
    end
  end
  klass = Sequel.set_temp_name(Class.new(self)){"Sequel::_Model(#{source.inspect})"}
  if source.is_a?(::Sequel::Database)
    klass.db = source
  else
    klass.set_dataset(source)
  end
  if cache_anonymous_models
    Sequel.synchronize{cache[source] = klass}
  end
  klass
end

def [](*args)

# => #'Bob', ...}>
Artist[name: 'Bob'] # SELECT * FROM artists WHERE (name = 'Bob') LIMIT 1

# => #1, ...}>
Artist[1] # SELECT * FROM artists WHERE id = 1

the given argument(s). If no object is returned by the dataset, returns nil.
object is given, it finds the first record whose primary key(s) match
If a hash is given, it is used as the conditions. If another
Returns the first record from the database matching the conditions.
def [](*args)
  args = args.first if args.size <= 1
  args.is_a?(Hash) ? first(args) : (primary_key_lookup(args) unless args.nil?)
end

def call(values)

probably should not be used by external code.
Requires that values be a hash where all keys are symbols. It
used by Sequel to initialize model instances when fetching records.
Initializes a model instance as an existing record. This constructor is
def call(values)
  o = allocate
  o.instance_variable_set(:@values, values)
  o
end

def check_non_connection_error(do_raise=require_valid_table)

and DatabaseDisconnectError.
Yield to the passed block and if do_raise is false, swallow Sequel::Errors other than DatabaseConnectionError
def check_non_connection_error(do_raise=require_valid_table)
  db.transaction(:savepoint=>:only){yield}
rescue Sequel::DatabaseConnectionError, Sequel::DatabaseDisconnectError
  raise
rescue Sequel::Error
  raise if do_raise
end

def clear_setter_methods_cache

Clear the setter_methods cache
def clear_setter_methods_cache
  @setter_methods = nil unless frozen?
end

def columns

# => [:id, :name]
Artist.columns

dataset) it will use Dataset#columns to find the columns.
schema, but in certain cases (e.g. models that are based on a joined
Generally, this will use the columns determined via the database
Returns the columns in the result set in their original order.
def columns
  return @columns if @columns
  return nil if frozen?
  set_columns(dataset.naked.columns)
end

def convert_input_dataset(ds)

this model's dataset.
Convert the given object to a Dataset that should be used as
def convert_input_dataset(ds)
  case ds
  when Symbol, SQL::Identifier, SQL::QualifiedIdentifier
    self.simple_table = db.literal(ds).freeze
    ds = db.from(ds)
  when SQL::AliasedExpression, LiteralString
    self.simple_table = nil
    ds = db.from(ds)
  when Dataset
    ds = ds.from_self(:alias=>ds.first_source) if ds.joined_dataset?
    self.simple_table = if ds.send(:simple_select_all?)
      ds.literal(ds.first_source_table).freeze
    end
    @db = ds.db
  else
    raise(Error, "Model.set_dataset takes one of the following classes as an argument: Symbol, LiteralString, SQL::Identifier, SQL::QualifiedIdentifier, SQL::AliasedExpression, Dataset")
  end
  set_dataset_row_proc(ds.clone(:model=>self))
end

def create(values = OPTS, &block)

end # INSERT INTO artists (name) VALUES ('Jim')
a.name = 'Jim'
Artist.create do |a|

# INSERT INTO artists (name) VALUES ('Bob')
Artist.create(name: 'Bob')

Creates instance using new with the given values and block, and saves it.
def create(values = OPTS, &block)
  new(values, &block).save
end

def dataset

Artist.dataset.all # SELECT * FROM artists

proxies many dataset methods to the underlying dataset.
In most cases, you don't need to call this directly, as Model
an +Error+ if there is no associated dataset for this class.
Returns the dataset associated with the Model class. Raises
def dataset
  @dataset || raise(Error, "No dataset associated with #{self}")
end

def dataset=(ds)

Alias of set_dataset
def dataset=(ds)
  set_dataset(ds)
end

def dataset_extend(mod, opts=OPTS)

public dataset methods.
module if the model has a dataset. Add dataset methods to the class for all
Add the module to the class's dataset_method_modules. Extend the dataset with the
def dataset_extend(mod, opts=OPTS)
  @dataset = @dataset.with_extend(mod) if @dataset
  reset_instance_dataset
  dataset_method_modules << mod
  unless opts[:create_class_methods] == false
    mod.public_instance_methods.each{|meth| def_model_dataset_method(meth)}
  end
end

def dataset_methods_module

default behavior.
This allows the methods to be overridden and call super with the
Module that the class methods that call dataset methods are kept in.
def dataset_methods_module
  return @dataset_methods_module if defined?(@dataset_methods_module)
  mod_name = "#{name}::@dataset_methods_module"
  Sequel.synchronize{@dataset_methods_module ||= Sequel.set_temp_name(Module.new){mod_name}}
  extend(@dataset_methods_module)
  @dataset_methods_module
end

def dataset_module(mod = nil, &block)

defined.
call the method on the dataset, assuming that the class method is not already
Any public methods in the dataset module will have class methods created that

performance.
methods is that they can take advantage of dataset caching to improve
The advantage of using these DatasetModule methods to define your dataset

select_append, select_group, where, and server.
group_append, having, limit, offset, order, order_append, order_prepend, select, select_all,
The following methods are supported: distinct, eager, exclude, exclude_having, grep, group, group_and_count,

# => "SELECT id, name, release_date FROM artists WHERE (release_date <= CURRENT_DATE) ORDER BY release_date"
Album.released.by_release_date.for_select_options.sql
# => "SELECT id, name, release_date FROM artists"
Album.for_select_options.sql
# => "SELECT * FROM artists ORDER BY release_date"
Album.by_release_date.sql
# => "SELECT * FROM artists WHERE (release_date <= CURRENT_DATE)"
Album.released.sql
end
select :for_select_options, :id, :name, :release_date
order :by_release_date, :release_date
where(:released, Sequel[:release_date] <= Sequel::CURRENT_DATE)
Album.dataset_module do

named dataset methods:
methods with the same names as the dataset methods, which can use to define
defines a dataset method that adds a filter. There are also a number of other
(a Module subclass), which allows you to call the subset method on them, which
Any anonymous modules created are actually instances of Sequel::Model::DatasetModule

# => :bar
Album.foo
# => :bar
Album.dataset.foo
end
end
:bar
def foo
Album.dataset_module do
# Usage with anonymous module

Album.dataset_module Sequel::ColumnsIntrospection
# Usage with existing module

Returns the module given or the anonymous module created.
dataset methods directly using the standard ruby def syntax.
if a block is given, it is module_evaled, allowing you do define
the underlying dataset. Otherwise an anonymous module is created, and
If given an argument, it should be a module, and is used to extend

This is the recommended way to add methods to model datasets.
a plugin with the methods defined in DatasetMethods.
Extend the dataset with a module, similar to adding
def dataset_module(mod = nil, &block)
  if mod
    raise Error, "can't provide both argument and block to Model.dataset_module" if block
    dataset_extend(mod)
    mod
  else
    @dataset_module ||= dataset_module_class.new(self)
    @dataset_module.module_eval(&block) if block
    dataset_extend(@dataset_module)
    @dataset_module
  end
end

def db

end # COMMIT
# INSERT INTO artists (name) VALUES ('Bob')
Artist.create(name: 'Bob')
Artist.db.transaction do # BEGIN

been created, raises an error.
Sequel::DATABASES. If no Sequel::Database object has
assumes the superclass's database, or the first object in
If this model doesn't have a database associated with it,
Returns the database associated with the Model class.
def db
  return @db if @db
  @db = self == Model ? Sequel.synchronize{DATABASES.first} : superclass.db
  raise(Error, "No database associated with #{self}: have you called Sequel.connect or #{self}.db= ?") unless @db
  @db
end

def db=(db)

sharding support, or consider using separate model classes per Database.
at runtime. If you have that need, you should look into Sequel's
Note that you should not use this to change the model's database

Artist.db = DB2
Artist = Class.new(Sequel::Model)
Sequel::Model.db = DB1

by subclasses, or to override the database used for specific models:
This can be used directly on Sequel::Model to set the default database to be used

have a dataset defined.
Should only be used if the Model class currently does not
Sets the database associated with the Model class.
def db=(db)
  raise Error, "Cannot use Sequel::Model.db= on model with existing dataset.  Use Sequel::Model.dataset= instead." if @dataset
  @db = db
end

def db_schema

# :name=>{:type=>:string, :primary_key=>false, ...}}
# {:id=>{:type=>:integer, :primary_key=>true, ...},
Artist.db_schema

Database#schema.
and values are hashes of information related to the column. See
from the database. This is a hash where keys are column symbols
Returns the cached schema information if available or gets it
def db_schema
  return @db_schema if @db_schema
  return nil if frozen?
  @db_schema = get_db_schema
end

def def_Model(mod)

end
end
# Uses Foo::DB[:my_baz]
class Baz < Model(:my_baz)

end
# Uses Foo::DB[:bars]
class Bar < Model

Model.plugin :prepared_statements
DB = Model.db = Sequel.connect(ENV['FOO_DATABASE_URL'])
Model.def_Model(self)
Model = Class.new(Sequel::Model)
module Foo

a namespace. Example:
making it easier to have custom model settings for all models under
defined, and allows you to define Model() methods on other modules,
method on the receiver. This is how the Sequel::Model() method is
Define a Model method on the given module that calls the Model
def def_Model(mod)
  model = self
  mod.define_singleton_method(:Model) do |source|
    model.Model(source)
  end
end

def def_bad_column_accessor(column)

Create a column accessor for a column with a method name that is hard to use in ruby code.
def def_bad_column_accessor(column)
  im = instance_methods
  overridable_methods_module.module_eval do
    meth = :"#{column}="
    unless im.include?(column)
      define_method(column){self[column]}
      alias_method(column, column)
    end
    unless im.include?(meth)
      define_method(meth){|v| self[column] = v}
      alias_method(meth, meth)
    end
  end
end

def def_column_accessor(*columns)

use a string to define the method for speed. For other columns names, use a block.
Create the column accessors. For columns that can be used as method names directly in ruby code,
def def_column_accessor(*columns)
  clear_setter_methods_cache
  columns, bad_columns = columns.partition{|x| /\A[A-Za-z_][A-Za-z0-9_]*\z/.match(x.to_s)}
  bad_columns.each{|x| def_bad_column_accessor(x)}
  im = instance_methods
  columns.each do |column|
    meth = :"#{column}="
    unless im.include?(column)
      overridable_methods_module.module_eval("def #{column}; self[:#{column}] end", __FILE__, __LINE__)
      overridable_methods_module.send(:alias_method, column, column)
    end
    unless im.include?(meth)
      overridable_methods_module.module_eval("def #{meth}(v); self[:#{column}] = v end", __FILE__, __LINE__)
      overridable_methods_module.send(:alias_method, meth, meth)
    end
  end
end

def def_column_alias(meth, column)

different name.
Create a column alias, where the column methods have one name, but the underlying storage uses a
def def_column_alias(meth, column)
  clear_setter_methods_cache
  overridable_methods_module.module_eval do
    define_method(meth){self[column]}
    define_method("#{meth}="){|v| self[column] = v}
  end
end

def def_model_dataset_method(meth)

Define a model method that calls the dataset method with the same name.
def def_model_dataset_method(meth)
  return if respond_to?(meth, true)
  mod = dataset_methods_module
  if meth.to_s =~ /\A[A-Za-z_][A-Za-z0-9_]*\z/
    mod.module_eval(<<END, __FILE__, __LINE__ + 1)
meth}(*args, &block); dataset.#{meth}(*args, &block) end
keywords :#{meth} if respond_to?(:ruby2_keywords, true)
  else
    mod.send(:define_method, meth){|*args, &block| dataset.public_send(meth, *args, &block)}
    # :nocov:
    mod.send(:ruby2_keywords, meth) if respond_to?(:ruby2_keywords, true)
    # :nocov:
  end
  mod.send(:alias_method, meth, meth)
end

def find(*args, &block)

# SELECT * FROM artists WHERE (name > 'M') LIMIT 1
Artist.find{name > 'M'}

# SELECT * FROM artists WHERE (name = 'Bob') LIMIT 1
Artist.find(name: 'Bob')

You are encouraged to use Model[] or Model.first instead of this method.
Finds a single record according to the supplied filter.
def find(*args, &block)
  first(*args, &block)
end

def find_or_create(cond, &block)

# INSERT INTO artists (name, hometown) VALUES ('Jim', 'Sactown')
# SELECT * FROM artists WHERE (name = 'Jim') LIMIT 1
Artist.find_or_create(name: 'Jim'){|a| a.hometown = 'Sactown'}

# INSERT INTO artists (name) VALUES ('Bob')
# SELECT * FROM artists WHERE (name = 'Bob') LIMIT 1
Artist.find_or_create(name: 'Bob')

return an object.
to +find+, but instead is passed to +create+ only if +find+ does not
exist. Unlike +find+ in that the block used in this method is not passed
Like +find+ but invokes create with given conditions when record does not
def find_or_create(cond, &block)
  find(cond) || create(cond, &block)
end

def freeze

Freeze a model class, disallowing any further changes to it.
def freeze
  return self if frozen?
  dataset_module.freeze
  overridable_methods_module.freeze
  if @dataset
    db_schema.freeze.each_value(&:freeze)
    columns.freeze
    setter_methods.freeze
  else
    @setter_methods = [].freeze
  end
  @dataset_method_modules.freeze
  @default_set_fields_options.freeze
  @plugins.freeze
  super
end

def get_db_schema(reload = reload_db_schema?)

it raises an error.
via the database if that will return inaccurate results or if
Get the schema from the database, fall back on checking the columns
def get_db_schema(reload = reload_db_schema?)
  set_columns(nil)
  return nil unless @dataset
  schema_hash = {}
  ds_opts = dataset.opts
  get_columns = proc{check_non_connection_error{columns} || []}
  schema_array = get_db_schema_array(reload) if db.supports_schema_parsing?
  if schema_array
    schema_array.each{|k,v| schema_hash[k] = v}
    # Set the primary key(s) based on the schema information,
    # if the schema information includes primary key information
    if schema_array.all?{|k,v| v.has_key?(:primary_key)}
      pks = schema_array.map{|k,v| k if v[:primary_key]}.compact
      pks.length > 0 ? set_primary_key(pks) : no_primary_key
    end
    if (select = ds_opts[:select]) && !(select.length == 1 && select.first.is_a?(SQL::ColumnAll))
      # We don't remove the columns from the schema_hash,
      # as it's possible they will be used for typecasting
      # even if they are not selected.
      cols = get_columns.call
      cols.each{|c| schema_hash[c] ||= {}}
      def_column_accessor(*schema_hash.keys)
    else
      # Dataset is for a single table with all columns,
      # so set the columns based on the order they were
      # returned by the schema.
      cols = schema_array.map{|k,v| k}
      set_columns(cols)
      # Also set the columns for the dataset, so the dataset
      # doesn't have to do a query to get them.
      dataset.send(:columns=, cols)
    end
  else
    # If the dataset uses multiple tables or custom sql or getting
    # the schema raised an error, just get the columns and
    # create an empty schema hash for it.
    get_columns.call.each{|c| schema_hash[c] = {}}
  end
  schema_hash
end

def get_db_schema_array(reload)

the schema information cannot be determined.
Get the array of schema information for the dataset. Returns nil if
def get_db_schema_array(reload)
  check_non_connection_error(false){db.schema(dataset, :reload=>reload)}
end

def get_setter_methods

that want to modify the methods used.
Uncached version of setter_methods, to be overridden by plugins
def get_setter_methods
  meths = instance_methods.map(&:to_s).select{|l| l.end_with?('=')} - RESTRICTED_SETTER_METHODS
  meths -= Array(primary_key).map{|x| "#{x}="} if primary_key && restrict_primary_key?
  meths
end

def has_dataset?

designed for subclassing, such as Sequel::Model itself.
but can be false if the model class is an abstract model class
Whether the model has a dataset. True for most model classes,
def has_dataset?
  !@dataset.nil?
end

def implicit_table_name

Foo::ArtistAlias.implicit_table_name # => :artist_aliases
Artist.implicit_table_name # => :artists

underscored, pluralized name of the class.
Returns the implicit table name for the model class, which is the demodulized,
def implicit_table_name
  pluralize(underscore(demodulize(name))).to_sym
end

def include(*mods)

may contain setter methods.
Clear the setter_methods cache when a module is included, as it
def include(*mods)
  clear_setter_methods_cache
  super
end

def inherited(subclass)

end
class Artist < Sequel::Model # Causes schema query

a model class is created:
Sequel queries the database to get schema information as soon as

are copied into the subclass.
is created. Also, make sure the inherited class instance variables
If possible, set the dataset for the model subclass as soon as it
def inherited(subclass)
  super
  ivs = subclass.instance_variables
  inherited_instance_variables.each do |iv, dup|
    if (sup_class_value = instance_variable_get(iv)) && dup
      sup_class_value = case dup
      when :dup
        sup_class_value.dup
      when :hash_dup
        h = {}
        sup_class_value.each{|k,v| h[k] = v.dup}
        h
      when Proc
        dup.call(sup_class_value)
      else
        raise Error, "bad inherited instance variable type: #{dup.inspect}"
      end
    end
    subclass.instance_variable_set(iv, sup_class_value)
  end
  unless ivs.include?(:@dataset)
    if @dataset && self != Model
      subclass.set_dataset(@dataset.clone, :inherited=>true)
    elsif (n = subclass.name) && !n.to_s.empty?
      db
      subclass.set_dataset(subclass.implicit_table_name)
    end
  end
end

def inherited_instance_variables

Proc :: Call with subclass to do the assignment
:hash_dup :: Assign hash with same keys, but dup all the values
:dup :: Dup object when assigning from superclass to subclass (mutable objects)
nil :: Assign directly from superclass to subclass (frozen objects)
Keys are instance variable symbols, values should be:
A hash of instance variables to automatically set up in subclasses.
def inherited_instance_variables
  {
    :@cache_anonymous_models=>nil,
    :@dataset_method_modules=>:dup,
    :@dataset_module_class=>nil,
    :@db=>nil,
    :@default_set_fields_options=>:dup,
    :@fast_instance_delete_sql=>nil,
    :@fast_pk_lookup_sql=>nil,
    :@plugins=>:dup,
    :@primary_key=>nil,
    :@raise_on_save_failure=>nil,
    :@raise_on_typecast_failure=>nil,
    :@require_modification=>nil,
    :@require_valid_table=>nil,
    :@restrict_primary_key=>nil,
    :@setter_methods=>nil,
    :@simple_pk=>nil,
    :@simple_table=>nil,
    :@strict_param_setting=>nil,
    :@typecast_empty_string_to_nil=>nil,
    :@typecast_on_assignment=>nil,
    :@use_transactions=>nil
  }
end

def late_binding_class_option(opts, default)

binding to the class later using constantize.
of the class to use as a string. The purpose is to allow late
:class_name option unless already present which contains the name
For the given opts hash and default name or :class option, add a
def late_binding_class_option(opts, default)
  case opts[:class]
    when String, Symbol
      # Delete :class to allow late binding
      class_name = opts.delete(:class).to_s
      if (namespace = opts[:class_namespace]) && !class_name.start_with?('::')
        class_name = "::#{namespace}::#{class_name}"
      end
      opts[:class_name] ||= class_name
    when Class
      opts[:class_name] ||= opts[:class].name
  end
  opts[:class_name] ||= '::' + ((name || '').split("::")[0..-2] + [camelize(default)]).join('::')
end

def load(values)

Calls #call with the values hash.
def load(values)
  call(values)
end

def method_added(meth)

Clear the setter_methods cache when a setter method is added.
def method_added(meth)
  clear_setter_methods_cache if meth.to_s.end_with?('=')
  super
end

def no_primary_key

Artist.primary_key # => nil
Artist.no_primary_key
Artist.primary_key # => :id

can cause issues, among which is that you won't be able to update records.
Mark the model as not having a primary key. Not having a primary key
def no_primary_key
  clear_setter_methods_cache
  self.simple_pk = @primary_key = nil
end

def overridable_methods_module

associations so that the methods can be overridden with +super+.
Module that the class includes that holds methods the class adds for column accessors and
def overridable_methods_module
  return @overridable_methods_module if defined?(@overridable_methods_module)
  mod_name = "#{name}::@overridable_methods_module"
  Sequel.synchronize{@overridable_methods_module ||= Sequel.set_temp_name(Module.new){mod_name}}
  include(@overridable_methods_module)
  @overridable_methods_module
end

def plugin(plugin, *args, &block)

the module using a the camelized plugin name under Sequel::Plugins.
require the plugin from sequel/plugins/#{plugin} and then attempt to load
to the plugin. If the plugin is a module, load it directly. Otherwise,
Loads a plugin for use with the model class, passing optional arguments
def plugin(plugin, *args, &block)
  m = plugin.is_a?(Module) ? plugin : plugin_module(plugin)
  if !m.respond_to?(:apply) && !m.respond_to?(:configure) && (!args.empty? || block)
    Deprecation.deprecate("Plugin #{plugin} accepts no arguments or block, and passing arguments/block to it", "Remove arguments and block when loading the plugin")
  end
  unless @plugins.include?(m)
    @plugins << m
    m.apply(self, *args, &block) if m.respond_to?(:apply)
    extend(m::ClassMethods) if m.const_defined?(:ClassMethods, false)
    include(m::InstanceMethods) if m.const_defined?(:InstanceMethods, false)
    if m.const_defined?(:DatasetMethods, false)
      dataset_extend(m::DatasetMethods, :create_class_methods=>false)
    end
  end
  m.configure(self, *args, &block) if m.respond_to?(:configure)
end

def plugin_module(plugin)

defined, the corresponding plugin required.
Returns the module for the specified plugin. If the module is not
def plugin_module(plugin)
  module_name = plugin.to_s.gsub(/(^|_)(.)/){|x| x[-1..-1].upcase}
  unless Sequel::Plugins.const_defined?(module_name, false)
    require "sequel/plugins/#{plugin}"
  end
  Sequel::Plugins.const_get(module_name)
end

def primary_key_hash(value)

Artist.primary_key_hash([1, 2]) # => {:id1=>1, :id2=>2}
Artist.primary_key_hash(1) # => {:id=>1}

raises an +Error+.
compatible type for the key. If the model does not have a primary key,
order. For a standard primary key, value should be an object with a
value such be an array with values for each primary key in the correct
Returns primary key attribute hash. If using a composite primary key
def primary_key_hash(value)
  case key = @primary_key
  when Symbol
    {key => value}
  when Array
    hash = {}
    key.zip(Array(value)){|k,v| hash[k] = v}
    hash
  else
    raise(Error, "#{self} does not have a primary key")
  end
end

def primary_key_lookup(pk)

is valid.
it is overridden by plugins which assume that the passed argument
This method should not be called with a nil primary key, in case

a static SQL optimization if the table and primary key are simple.
Find the row in the dataset that matches the primary key. Uses
def primary_key_lookup(pk)
  if sql = @fast_pk_lookup_sql
    sql = sql.dup
    ds = dataset
    ds.literal_append(sql, pk)
    ds.fetch_rows(sql){|r| return ds.row_proc.call(r)}
    nil
  else
    dataset.first(primary_key_hash(pk))
  end
end

def qualified_primary_key(qualifier=table_name)

# SELECT * FROM artists ORDER BY artists.id
Artist.order(Artist.qualified_primary_key)

raises an +Error+.
the table_name otherwise. If the model does not have a primary key,
the model's primary key. Uses the given qualifier if provided, or
Return a qualified identifier or array of qualified identifiers for
def qualified_primary_key(qualifier=table_name)
  case key = @primary_key
  when Symbol
    SQL::QualifiedIdentifier.new(qualifier, key)
  when Array
    key.map{|k| SQL::QualifiedIdentifier.new(qualifier, k)}
  else
    raise(Error, "#{self} does not have a primary key")
  end
end

def qualified_primary_key_hash(value, qualifier=table_name)

# SELECT * FROM artists WHERE (artists.id = 1)
Artist.where(Artist.qualified_primary_key_hash(1))

to be qualified. If the model does not have a primary key, raises an +Error+.
plan to join other tables to this table and you want the column references
qualifier if provided, or the table_name otherwise. This is useful if you
Return a hash where the keys are qualified column references. Uses the given
def qualified_primary_key_hash(value, qualifier=table_name)
  case key = @primary_key
  when Symbol
    {SQL::QualifiedIdentifier.new(qualifier, key) => value}
  when Array
    hash = {}
    key.zip(Array(value)){|k,v| hash[SQL::QualifiedIdentifier.new(qualifier, k)] = v}
    hash
  else
    raise(Error, "#{self} does not have a primary key")
  end
end

def reload_db_schema?

Whether to reload the database schema by default, ignoring any cached value.
def reload_db_schema?
  false
end

def reset_fast_pk_lookup_sql

are used, or set it to nil if not used.
Reset the cached fast primary lookup SQL if a simple table and primary key
def reset_fast_pk_lookup_sql
  @fast_pk_lookup_sql = if @simple_table && @simple_pk
    "SELECT * FROM #{@simple_table} WHERE #{@simple_pk} = ".freeze
  end
  @fast_instance_delete_sql = if @simple_table && @simple_pk
    "DELETE FROM #{@simple_table} WHERE #{@simple_pk} = ".freeze
  end
end

def reset_instance_dataset

should be used whenever the model's dataset is modified.
Reset the instance dataset to a modified copy of the current dataset,
def reset_instance_dataset
  @instance_dataset = @dataset.limit(1).naked.skip_limit_check if @dataset
end

def restrict_primary_key

parent class has used +unrestrict_primary_key+.
this is the default, this only make sense to use in a subclass where the
Restrict the setting of the primary key(s) when using mass assignment (e.g. +set+). Because
def restrict_primary_key
  clear_setter_methods_cache
  @restrict_primary_key = true
end

def restrict_primary_key?

restricted, true by default.
Whether or not setting the primary key(s) when using mass assignment (e.g. +set+) is
def restrict_primary_key?
  @restrict_primary_key
end

def set_columns(new_columns)

Set the columns for this model and create accessor methods for each column.
def set_columns(new_columns)
  @columns = new_columns
  def_column_accessor(*new_columns) if new_columns
  @columns
end

def set_dataset(ds, opts=OPTS)

end
class Artist < Sequel::Model(DB[:tbl_artists])
# dataset

end
class Artist < Sequel::Model(:tbl_artists)
# table name

set the table name or dataset when creating the model class:
You should avoid calling this method directly if possible. Instead you should

sharding support, or creating a separate Model class per dataset
at runtime. If you have that need, you should look into Sequel's
Note that you should not use this to change the model's dataset

based on the given dataset.
It also attempts to determine the database schema for the model,

Returns self.
database with the table name given. Other arguments raise an +Error+.
dataset. If a dataset is not used, a dataset is created from the current
If a dataset is used, the model's database is changed to the database of the given
(all specifying a table name in the current database), or a +Dataset+.
SQL::AliasedExpression
+LiteralString+, SQL::Identifier, SQL::QualifiedIdentifier,
Sets the dataset associated with the Model class. +ds+ can be a +Symbol+,
def set_dataset(ds, opts=OPTS)
  inherited = opts[:inherited]
  @dataset = convert_input_dataset(ds)
  @require_modification = @dataset.provides_accurate_rows_matched? if require_modification.nil?
  if inherited
    self.simple_table = superclass.simple_table
    @columns = superclass.instance_variable_get(:@columns)
    @db_schema = superclass.instance_variable_get(:@db_schema)
  else
    @dataset = @dataset.with_extend(*@dataset_method_modules.reverse)
    @db_schema = get_db_schema
  end
  @fast_pk_lookup_sql = @fast_instance_delete_sql = nil unless @dataset.supports_placeholder_literalizer?
  reset_instance_dataset
  self
end

def set_dataset_row_proc(ds)

Set the dataset's row_proc to the current model.
def set_dataset_row_proc(ds)
  ds.with_row_proc(self)
end

def set_primary_key(key)

end
set_primary_key [:taggable_id, :tag_id]
# composite key
class Tagging < Sequel::Model

end
set_primary_key :person_id
# regular key
class Person < Sequel::Model

determine the primary key to use, so this method is not needed often.
or use +no_primary_key+. On most adapters, Sequel can automatically
or a composite primary key. To not use a primary key, set to nil
Sets the primary key for this model. You can use either a regular
def set_primary_key(key)
  clear_setter_methods_cache
  if key.is_a?(Array)
    if key.length < 2
      key = key.first
    else
      key = key.dup.freeze
    end
  end
  self.simple_pk = if key && !key.is_a?(Array)
    (@dataset || db).literal(key).freeze
  end
  @primary_key = key
end

def setter_methods

Cache of setter methods to allow by default, in order to speed up mass assignment.
def setter_methods
  @setter_methods || (@setter_methods = get_setter_methods)
end

def simple_pk=(pk)

Reset the fast primary key lookup SQL when the simple_pk value changes.
def simple_pk=(pk)
  @simple_pk = pk
  reset_fast_pk_lookup_sql
end

def simple_table=(t)

Reset the fast primary key lookup SQL when the simple_table value changes.
def simple_table=(t)
  @simple_table = t
  reset_fast_pk_lookup_sql
end

def table_name

Sequel::Model(Sequel[:foo].as(:bar)).table_name # => :bar
Sequel::Model(:foo).table_name # => :foo
Artist.table_name # => :artists

is aliased, returns the aliased name.
Returns name of primary table for the dataset. If the table for the dataset
def table_name
  dataset.first_source_alias
end

def unrestrict_primary_key

Artist.set(id: 1) # No Error
Artist.unrestrict_primary_key
Artist.set(id: 1) # Error

Using this method can open up security issues, be very careful before using it.
Allow the setting of the primary key(s) when using the mass assignment methods.
def unrestrict_primary_key
  clear_setter_methods_cache
  @restrict_primary_key = false
end

def with_pk(pk)

Return the model instance with the primary key, or nil if there is no matching record.
def with_pk(pk)
  primary_key_lookup(pk)
end

def with_pk!(pk)

Return the model instance with the primary key, or raise NoMatchingRow if there is no matching record.
def with_pk!(pk)
  with_pk(pk) || raise(NoMatchingRow.new(dataset))
end