sequel Documentation

Sequel: The Database Toolkit for Ruby

5,097 stars Ruby Ruby 63 files ยท ~125,425 tokens
RAW Doc

Technical Documentation: jeremyevans/sequel

โ„น๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference

Doc Release Notes 1.0 (`doc/release_notes/1.0.txt`)

=== New code organization

Sequel is now divided into two parts: sequel_core and sequel_model.
These two parts are distributed as two separate gems. The sequel gem
bundles sequel_core and sequel_model together. If you don't use
Sequel::Model in your code, you can just install and use sequel_core.

=== New model hooks implementation

The hooks implementation have been rewritten from scratch, is much
more robust and offers a few new features:

  • More ways to define hooks: hooks can now be defined by supplying a
    block or a method name, or by overriding the hook instance method.

  • Inheritable hooks: Hooks can now be inherited, which means that you
    can define general hooks in a model superclass, and use them in
    subclasses. You can also define global hooks on Sequel::Model that
    will be invoked for all model classes.

  • Hook chains can be broken by returning false from within the hook.

  • New after_initialize hook, invoked after instance initialization.

  • The hook invocation order can no longer be changed. Hooks are
    invoked in order of definition, from the top of the class hierarchy
    (that is, from Sequel::Model) down to the specific class.

=== Miscellanea

  • Removed deprecated adapter stubs, and all other deprecations in both
    sequel_core and sequel_model.

  • Fixed String#to_time to raise error correctly for invalid time
    stamps.

  • Fixed error behavior when parse_tree or ruby2ruby are not available.


Doc Release Notes 1.1 (`doc/release_notes/1.1.txt`)

=== DRY Sequel models

With the new Sequel release you no longer need to explicitly specify
the table
name for each model class, assuming your model name is the singular of
the
table name (just like in ActiveRecord or DataMapper):

class UglyBug < Sequel::Model
end

UglyBug.table_name #=> :ugly_bugs

=== New model validations and support for virtual attributes

Sequel model now include validation functionality which largly follows
the
validations offered in ActiveRecord. Validations can be checked
anytime by
calling Model#valid?, with validation errors accessible through
Model#errors:

class Item < Sequel::Model
validates_presence_of :name
end

my_item = Item.new
my_item.valid? #=> false
my_item.errors.full_messages #=> ["name is not present"]

The Model#save method has been changed to check for validity before
saving. If
the model instance is not valid, the #save method returns false
without saving
the instance. You can also bypass the validity test by calling
Model#save!
instead.

Model classes also now support virtual attributes, letting you assign
values to
any attribute (virtual or persistent) at initialization time:

class User < Sequel::Model
attr_accessor :password
end

u = User.new(:password => 'blah', ...)
u.password #=> 'blah'

Also, virtual attributes can be validated just like persistent
attributes.

=== Other changes (long list!)

  • Added Model#reload as alias to Model#refresh.

  • Changed Model.create to accept a block (#126).

  • Fixed Model#initialize to accept nil values (#115).

  • Added Model#update_with_params method with support for virtual
    attributes and auto-filtering of unrelated parameters, and changed
    Model.create_with_params to support virtual attributes (#128).

  • Fixed Model.dataset to correctly set the dataset if using implicit
    naming or inheriting the superclass dataset (thanks celldee).

  • Finalized support for virtual attributes.

  • Fixed Model#set to work with string keys (#143).

  • Fixed Model.create to correctly initialize instances marked as new
    (#135).

  • Fixed Model#initialize to convert string keys into symbol keys. This
    also fixes problem with validating objects initialized with string
    keys (#136).

  • Added Dataset#table_exists? convenience method.

  • Changed Dataset#group_and_count to accept multiple columns (#134).

  • Added Dataset#select_all method.

  • Added Dataset#select_more, Dataset#order_more methods (#129).

  • Fixed Dataset#count to work correctly for grouped datasets (#144).

  • Fixed joining datasets using aliased tables (#140).

  • Added support for UNSIGNED constraint, used in MySQL? (#127).

  • Implemented constraint definitions inside Database#create_table.

  • Enhanced Database.connect to accept options with string keys, so it
    can now accept options loaded from YAML files. Database.connect also
    automatically converts :username option into :user for compatibility
    with existing YAML configuration files for AR and DataMapper.

  • Changed ODBC::Database to support connection using driver and
    database name, also added support for untitled columns in
    ODBC::Dataset (thanks Leonid Borisenko).

  • Changed MySQL adapter to support specifying socket option.

  • Fixed MySQL adapter to correctly format foreign key definitions
    (#123).

  • Changed MySQL::Dataset to allow HAVING clause on ungrouped datasets,
    and put HAVING clause before ORDER BY clause (#133).

  • Changed mysql adapter to default to localhost if :host option is not
    specified (#114).

  • Added String#to_date. Updated mysql adapter to use String#to_date
    for mysql date types (thanks drfreeze).

  • Fixed postgres adapter to define PGconn#async_exec as alias to #exec
    if not defined (for pure-ruby postgres driver).

  • Changed postgres adapter to quote column references using double
    quotes.

  • Applied patch for oracle adapter: fix behavior of limit and offset,
    transactions, #table_exists?, #tables and additional specs (thanks
    Liming Lian #122).

  • Added support additional field types in postgresql adapter (#146).

  • Added support for date field types in postgresql adapter (#145).

  • Added support for limiting and paginating datasets with fixed SQL,
    e.g. using Database#fetch.

  • Added new Dataset#from_self method that returns a dataset selecting
    from the original dataset.

  • Allow for additional filters on a grouped dataset (#119 and #120)

  • Refactored Sequelizer to use Proc#to_sexp (method provided by r2r).

  • Fixed bin/sequel to require sequel_model if available.


Doc Release Notes 1.3 (`doc/release_notes/1.3.txt`)

=== Better model associations

The latest release of sequel_model includes a new associations
functionality written by Jeremy Evans which replaces the old relations
code in previous versions. Please note that this version is not
completely backward-compatible and you should therefore upgrade with
caution.

The new implementation supports three kinds of relations: one_to_many,
many_to_one and many_to_many, which correspond to has_many, belongs_to
and has_and_belongs_to_many relations in ActiveRecord. In fact, the
new implementation includes aliases for ActiveRecord association macros
and is basically compatible with ActiveRecord conventions. It also
supports DRY implicit class name references. Here's a simple example:

class Author < Sequel::Model
has_many :books # equivalent to one_to_many
end

class Book < Sequel::Model
belongs_to :author # equivalent to many_to_one
has_and_belongs_to_many :categories # equivalent to many_to_many
end

class Category < Sequel::Model
has_and_belongs_to_many :books
end

These macros will create the following methods:

  • Author#books, Author#add_book, Author#remove_book
  • Book#author, Book#categories, Book#add_category,
    Book#remove_category
  • Category#books, Category#add_book, Category#remove_book

Unlike ActiveRecord, one_to_many and many_to_many association methods
return a dataset:

a = Author[1234]
a.books.sql #=> 'SELECT * FROM books WHERE (author_id = 1234)'

You can also tell Sequel to cache the association result set and
return it as an array:

class Author < Sequel::Model
has_many :books, :cache => true
end

Author[1234].books.class #=> Array

You can of course bypass the defaults and specify class names and key
names:

class Node < Sequel::Model
belongs_to :parent, :class => Node
belongs_to :session, :key => :producer_id
end

Another useful option is :order, which sets the order for the
association dataset:

class Author < Sequel::Model
has_many :books, :order => :title
end

Author[1234].books.sql #=> 'SELECT * FROM books WHERE (author_id =
1234) ORDER BY title'

More information about associations can be found in the Sequel
documentation.

=== Other changes

  • Added configuration file for running specs (#186).

  • Changed Database#drop_index to accept fixed arity (#173).

  • Changed column definition sql to put UNSIGNED constraint before
    unique in order to satisfy MySQL (#171).

  • Enhanced MySQL adapter to support load data local infile_, added
    compress option for mysql connection by default (#172).

  • Fixed bug when inserting hashes in array tuples mode.

  • Changed SQLite adapter to catch RuntimeError raised when executing a
    statement and raise Error::InvalidStatement with the offending SQL and
    error message (#188).

  • Fixed Dataset#reverse to not raise for unordered dataset (#189).

  • Added Dataset#unordered method and changed #order to remove order if
    nil is specified (#190).

  • Fixed reversing order of ASC expression (#164).

  • Added support for :null => true option when defining table columns
    (#192).

  • Fixed Symbol#method_missing to accept variable arity (#185).


Doc Release Notes 1.4.0 (`doc/release_notes/1.4.0.txt`)

Eager loading for all types of associations:

Artist.eager(:albums).all
Album.eager(:artist, :genre, :tracks).all
Album.eager(:artist).eager(:genre).eager(:tracks).all
Album.filter(:year=>2008).eager(:artist).all

Eager loading supports cascading to an unlimited depth, and doesn't have
any aliasing issues:

Artist.eager(:albums=>:tracks).all
Artist.eager(:albums=>{:tracks=>:genre}).all

Unfortunately, eager loading comes at the expense of a small amount of
backward compatibility. If you were using uncached associations (the
default in sequel_model 0.5), they no longer work the same way. Now,
all associations act as if :cache=>true (which is now set for all
associations, so if you wrote a tool that worked with both cached and
uncached associations, it should still work).

One to many associations now populate the corresponding many to one
instance variable (even when eagerly loaded):

Assuming: Album.one_to_many :tracks

album = Album.first

This following code is only one query,

not a query for the album and one for each track

album.tracks.each{|t| puts t.album.name}

ActiveRecord style has_many :through associations are now supported via
many_to_many. many_to_many will no longer select the entire result set,
just the columns of the associated table (and not the join table), so it
works for both has_and_belongs_to_many (simple join table) and has_many
:through (join table model) scenarios. If you want to include all or
part of the join table attributes, see the :select option for
many_to_many associations.

We reduced the number of gems from three (sequel, sequel_core,
sequel_model) to two (sequel, sequel_core). Basically, sequel_model is
now just sequel, and the old sequel gem metapackage is no longer. There
isn't a reason to have a gem metapackage for two gems when one
(sequel_model) depends on the other (sequel_core). This required a
version bump for the model part of sequel from 0.5.0.2 to 1.4.0 (since
the previous sequel gem version was 1.3).

Sequel 1.4.0 has fixes for 11 trackers issues, including fixes to the
MySQL and PostgreSQL adapters.

We have switched the source control repository for Sequel from Google
Code (which uses subversion) to github (which uses git). If you would
like to contribute to Sequel, please fork the github repository, make
your changes, and send a pull request. As before, posting patches on
the Google Code issue tracker is fine as well.


Doc Release Notes 1.5.0 (`doc/release_notes/1.5.0.txt`)

You can now graph a dataset and have the result split into component
tables:

DB[:artists].graph(:albums, :artist_id=>:id).first

=> {:artists=>{:id=>artists.id, :name=>artists.name}, \

:albums=>{:id=>albums.id, :name=>albums.name,

:artist_id=>albums.artist_id}}

This aliases columns if necessary so they don't stomp on each other,
which
is what usually happens if you just join the tables:

DB[:artists].left_outer_join(:albums, :artist_id=>:id).first

=> {:id=>(albums.id||artists.id),

:name=>(albums.name||artist.names),
:artist_id=>albums.artist_id}

Models can use graph as well, in which case the values will be model
objects:

Artist.graph(Album, :artist_id=>:id)

=> {:artists=>#, :albums=>#}

Models can now eager load via .eager_graph, which will load all the
results
and all associations in a single query. This is necessary if you want
to
filter on columns in associated tables. It works exactly the same way
as
.eager, and supports cascading of associations as well:

Artist.one_to_many :albums

Album.one_to_many :tracks

Track.many_to_one :genre

Artist.eager_graph(:albums=>{:tracks=>:genre}).filter(
:tracks_name=>"Firewire").all

This will give you all artists have have an album with a track named
"Firewire", and calling .albums on one of those artists will only return
albums that have a track named "Firewire", and calling .tracks on one of
those albums will return only the track(s) named "Firewire".

You can use set_graph_aliases to select specific columns:

DB[:artists].graph(:albums, :artist_id=>:id).set_graph_aliases(
:artist_name=>[:artists, :name], :album_name=>[:albums,
:name]).first

=> {:artists=>{:name=>artists.name}, :albums=>{:name=>albums.name}}

You can use eager_graph with set_graph_aliases to have eager loading
with
control over the SELECT clause.

All associations now update their reciprocal associations whenever the
association methods are used, so you don't need to refresh the
association or model to have the reciprocal association updated:

Album.many_to_one :band
Band.one_to_many :albums

Note that all of these associations are cached,

so after the first access there are no additional

database queries to fetch associated records.

many_to_one setter adds to reciprocal association

band1.albums # => []
album1.band = band1
band1.albums # => [album1]
band2.albums # => []
album1.band = band2
band1.albums # => []
band2.albums # => [album1]
album1.band = band2
band2.albums # => [album1]
album1.band = nil
band2.albums # => []

one_to_many add_* method sets reciprocal association

one_to_many remove_* method removes reciprocal association

album1.band # => nil
band1.add_album(album1)
album1.band # => band1
band2.add_album(album1)
album1.band # => band2
band2.remove_album(album1)
album1.band # => nil

Post.many_to_many :tags
Tag.many_to_many :posts

many_to_many add_* method adds to reciprocal association

many_to_many remove_* method removes from reciprocal association

post1.tags # => []
tag1.posts # => []
tag1.add_post(post1)
post1.tags # => [tag1]
tag1.posts # => [post1]
tag1.remove_post(post1)
post1.tags # => []
tag1.posts # => []
post1.add_tag(tag1)
post1.tags # => [tag1]
tag1.posts # => [post1]
post1.remove_tag(tag1)
post1.tags # => []
tag1.posts # => []

The MySQL and PostgreSQL adapters now support index types:

index :some_column, :type => :hash # or :spatial, :full_text, :rtree,
etc.

Starting in Sequel 1.5.0, some methods are deprecated. These methods
will be
removed in Sequel 2.0.0. The deprecation framework is fairly flexible.
You
can choose where the messages get sent:

Sequel::Deprecation.deprecation_message_stream = STDERR # the default
Sequel::Deprecation.deprecation_message_stream =
File.new('deprecation.txt', 'wb') # A file
Sequel::Deprecation.deprecation_message_stream = nil # ignore the
messages

You can even have all deprecation messages accompanied by a traceback,
so you
can see exactly where in your code you are using a deprecated method:

Sequel::Deprecation.print_tracebacks = true

All deprecation methods come with an message telling you what
alternative code
will work.

In addition to deprecating some methods, we removed the ability to have
arrays returned instead of hashes. The array code still had debugging
messages
left it in, and we are not aware of anyone using it. Hashes have been
returned
by default since Sequel 0.3.

We have also removed the Numeric date/time extensions (e.g. 3.days.ago).
The
existing extensions were incomplete, better ones are provided elsewhere,
and the extensions were not really related to Sequel's purpose.

Sequel no longer depends on ParseTree, RubyInline, or ruby2ruby. They
are
still required to use the block filters. Sequel's only gem dependency
is on
the tiny metaid.

Sequel 1.5.0 has fixes for 12 tracker issues, including fixes to the
Informix,
MySQL, ODBC, ADO, JDBC, Postgres, and SQLite adapters.


Doc Release Notes 2.0.0 (`doc/release_notes/2.0.0.txt`)

Blockless Filter Expressions

Before 2.0.0, in order to specify complex SQL expressions, you
either had to resort to writing the SQL yourself in a string or
using an expression inside a block that was parsed by ParseTree.
Because ParseTree was required, only ruby 1.8.* was supported, and
supporting other ruby versions (ruby 1.9, JRuby, Rubinius) would
never be possible.

With 2.0.0, you no longer need to use a block to write complex SQL
expressions. The basics of the blockless filters are the usual
arithmetic, inequality, and binary operators:

  • = addition
  • = subtraction
  • = multiplication
    / = division

= greater than
< = less than
= = greater than or equal to
<= = less than or equal to
~ = negation
& = AND
| = OR

You can use these operators on Symbols, LiteralStrings, and other
Sequel::SQL::Expressions. Note that there is no equal operator or
not equal operator, to specify those, you use a Hash.

Here are some examples:

Ruby code => SQL WHERE clause

:active => active
~:active => NOT active
~~:active => active

:active => not active
:is_true[] => is_true()
  ~:is_true[] => NOT is_true()
  :x > 100 => (x > 100)
  :x < 100.01 => (x < 100.01)
  :x <= 0 => (x <= 0)
  :x >= 1 => (x >= 1)
  ~(:x > 100) => (x <= 100)
  {:x => 100} => (x = 100)
  {:x => 'a'} => (x = 'a')
  {:x => nil} => (x IS NULL)
  ~{:x => 100} => (x != 100)
  ~{:x => 'a'} => (x != 'a')
  ~{:x => nil} => (x IS NOT NULL)
  {:x => /a/} => (x ~ 'blah') # Default, MySQL different
  ~{:x => /a/} => (x !~ 'blah') # Default, MySQL different
  :x.like('a') =>  (x LIKE 'a')
  ~:x.like('a') =>  (x NOT LIKE 'a')
  :x.like(/a/) => (x ~ 'a') # Default, MySQL different
  ~:x.like('a', /b/) => ((x NOT LIKE 'a') AND (x !~ 'b')) # Default
  ~{:x => 1..5} => ((x < 1) OR (x > 5))
  ~{:x => DB[:items].select(:i)} => (x NOT IN (SELECT i FROM items))
  ~{:x => [1,2,3]} => (x NOT IN (1, 2, 3))
  :x + 1 > 100 => ((x + 1) > 100)
  (:x * :y) < 100.01 => ((x * y) < 100.01)
  (:x - :y/2) >= 100 => ((x - (y / 2)) >= 100)
  (((:x - :y)/(:x + :y))*:z) <= 100 => ((((x - y) / (x + y)) * z) <=
100)
  ~((((:x - :y)/(:x + :y))*:z) <= 100) => ((((x - y) / (x + y)) * z) >
100)
  :x & :y => (x AND y)
  :x & :y & :z => ((x AND y) AND z)
  :x & {:y => :z} => (x AND (y = z))
  {:y => :z} & :x => ((y = z) AND x)
  {:x => :a} & {:y => :z} => ((x = a) AND (y = z))
  (:x > 200) & (:y < 200) => ((x > 200) AND (y < 200))
  :x | :y => (x OR y)
  :x | :y | :z => ((x OR y) OR z)
  :x | {:y => :z} => (x OR (y = z))
  {:y => :z} | :x => ((y = z) OR x)
  {:x => :a} | {:y => :z} => ((x = a) OR (y = z))
  (:x > 200) | (:y < 200) => ((x > 200) OR (y < 200))
  (:x | :y) & :z => ((x OR y) AND z)
  :x | (:y & :z) => (x OR (y AND z))
  (:x & :w) | (:y & :z) => ((x AND w) OR (y AND z))
  ~((:x | :y) & :z) => ((NOT x AND NOT y) OR NOT z)
  ~((:x & :w) | (:y & :z)) => ((NOT x OR NOT w) AND (NOT y OR NOT z))
  ~((:x > 200) | (:y & :z)) => ((x <= 200) AND (NOT y OR NOT z))
  ~('x'.lit + 1 > 100) => ((x + 1) <= 100)
  'x'.lit.like(/a/) => (x ~ 'a') # (x ~ \'a\')

None of these require blocks, you can use any directly in a call to
filter:

  DB[:items].filter((:price * :tax) - :discount > 100)
  # => SELECT * FROM items WHERE (((price * tax) - discount) > 100)
  DB[:items].filter(:active & ~:archived)
  # => SELECT * FROM items WHERE (active AND NOT archived)

SQL String Concatenation
------------------------

Sequel now has support for expressing SQL string concatenation in an
easy way:

  [:name, :title].sql_string_join(" - ")
  # SQL:  name || ' - ' || title

You can use this in selecting columns, creating filters, ordering
datasets, and possibly elsewhere.

Schema Reflection Support/Typecasting on Assignment
---------------------------------------------------

When used with PostgreSQL, MySQL, or SQLite, Sequel now has the
ability to get information from the database's schema in regards
to column types:

  DB.schema(:artist)
  => [[:id, {:type=>:integer, :db_type=>"integer", :max_chars=>0
     :numeric_precision=>32, :allow_null=>false,
     :default=>"nextval('artist_id_seq'::regclass)"}], [:name,
     {:type=>:string, :default=>nil, :db_type=>"text",
     :numeric_precision=>0, :allow_null=>true, :max_chars=>0}]]

Models now use this information to typecast values on attribute
assignment. For example, if you have an integer column named number
and a text (e.g. varchar) column named title:

  1.5.1:
    model.number = '1'
    model.number # => '1'
    model.title = 1
    model.title # => 1
  2.0.0:
    model.number = '1'
    model.number # => 1
    model.title = 1
    model.title # => '1'

Typecasting can be turned off on a global, per class, and per object
basis:

  Sequel::Model.typecast_on_assignment = false # Global
  Album.typecast_on_assignment = false # Per Class
  Album.new.typecast_on_assignment = false # Per Object

Typecasting is somewhat strict, it does not allow obviously bogus
data to be used:

  model.number = 'a' # Raises error

This is in contrast to how some other ORMs handle the situation:

  model.number = 'a'
  model.number # => 0

If Sequel is being used with a web framework and you want to display
friendly error messages to the user, you should probably turn
typecasting off and set up the necessary validations in your models.

Model Association Improvements
------------------------------

Associations can now be eagerly loaded even if they have a block,
though the block should not rely on being evaluated in the context
of an instance. This allows you filter on associations when eagerly
loading:

  Artist.one_to_many :albums_with_10_tracks, :class=>:Album do |ds|
    ds.filter(:num_tracks => 10)
  end
  Artist.filter(:name.like('A%)).eager(:albums_with_10_tracks).all
  # SELECT * FROM artists WHERE (name LIKE 'A%')
  # SELECT albums.* FROM albums WHERE ((artist_id IN (...)) AND
  #   (num_tracks = 10))

Associations now have a remove_all_ method for removing all
associated objects in a single query:

  Artist.many_to_many :albums
  Artist[1].remove_all_albums
  # DELETE FROM albums_artists WHERE artist_id = 1

  Artist.one_to_many :albums
  Artist[1].remove_all_albums
  # UPDATE albums SET artist_id = NULL WHERE artist_id = 1

All associations can specify a :select option to change which columns
are selected.  Previously only many to many associations supported
this.

The SQL used when eagerly loading through eager_graph can be
modified via the :graph_join_type, :graph_conditions, and
:graph_join_conditions options.

:graph_join_type changes the join type from the default of
:left_outer.  This can be useful if you do not want any
albums that don't have an artist in the result set:

  Album.many_to_one :artist, :graph_join_type=>:inner
  Album.eager_graph(:artist).sql
  # SELECT ... FROM albums INNER JOIN artists ...

:graph_conditions adds conditions on the join to the table you are
joining, the eager_graph equivalent of an association block argument
in eager. It takes either a hash or an array where all elements
are arrays of length two, similar to join_table, where key symbols
specify columns in the joined table and value symbols specify
columns in the last joined or primary table:

  Album.many_to_one :artist, :graph_conditions=>{:active=>true}
  Album.eager_graph(:artist).sql
  # SELECT ... FROM albums LEFT OUTER JOIN artists ON ((artists.id =
  #   albums.artist_id) AND (artists.active = 't'))

:graph_join_table_conditions exists for many to many associations only,
and operates the same as :graph_conditions, except it specifies a
condition on the many to many join table instead of the associated
model's table. This is necessary if the join table is also model
table with other columns on which you may want to filter:

  Album.many_to_many :genres, :join_table=>:ag, \
    :graph_join_table_conditions=>{:active=>true}
  Album.eager_graph(:genres).sql
  # SELECT ... FROM albums LEFT OUTER JOIN ag ON ((ag.album_id =
      albums.id) AND (ag.active = 't')) LEFT OUTER JOIN genres ON
      (genres.id = ag.genre_id)

Other Small Improvements
------------------------

* Dataset#invert returns a dataset that matches all records not
  matching the current filter.
* Dataset#unfiltered returns a dataset that has any filters removed.
* Dataset#last_page? and Dataset#first_page? for paginated datasets.
* The sequel command line tool now support an -E or --echo argument
  that logs all SQL to the standard output.  It also can take a path
  to a yaml file with database connection options, in addition to a
  database URL.
* Databases can now have multiple SQL loggers, so you can log to the
  standard output as well as a file.
* SQL identifiers (columns and tables) are now quoted by default (you
  can turn this off via Sequel.quote_identifiers = false if need be).
* Sequel.connect now takes an optional block that will disconnect the
  database when the block finishes.
* AlterTableGenerator now has add_primary_key and add_foreign_key
  methods.
* Running the specs without ParseTree installed skips the specs that
  require ParseTree.
* You can use an array of arrays instead of a hash when specifying
  conditions, which may be necessary in certain situations where
  you would be using the same hash key more than once.
* Almost all documentation for Sequel was updated for 2.0.0, so if you
  found Sequel documentation lacking before, check out the new RDoc
  pages.
* There have been many minor refactoring improvements, the code
  should now be easier to read and follow.
* Sequel now has no external dependencies.
* Sequel::Models now have before_validation and after_validation
  hooks.
* Sequel::Model hooks that return false cause the methods that call
  them (such as save) to return false.
* Sequel::Models can now load their schema on first instantiation,
  instead of when they are created, via
  Sequel::Model.lazy_load_schema=.  This is helpful for certain
  web frameworks that reload all models on every request.
* Hook methods that use blocks can now include an optional tag,
  which allows them to work well with web frameworks that load source
  files every time they are modified.

The PostgreSQL adapter has been rewritten and now supports ruby-pg.
There have also been improvements in the following adapters: DBI,
MySQL, SQLite, Oracle, and MSSQL.

All of the methods that have been deprecated in 1.5.0 have now been
removed.  If you are want to upgrade to Sequel 2.0.0 from version 1.4.0
or previous, upgrade to 1.5.1 first, fix all of the deprecation
warnings that show up, and then upgrade to 2.0.0.

There were some backwards incompatible changes made in 2.0.0 beyond the
removal of deprecated methods.  These are:

* Inflector is no longer used, the inflection methods were moved
  directly into String (where they belong because inflections only
  make sense for strings).  So to override singularization
  or pluralization rules, use String.inflections instead of
  Inflector.inflections.
* MySQL tinyints are now returned as boolean values instead of
  integers.  MySQL doesn't have a boolean type, and usually it
  is recommended to use tinyint for a boolean column.
* You can no longer pass an array to Dataset#order or Dataset#select,
  you need to pass each argument separately (the * operator is your
  friend).
* You must use '?' instead of '(?)' when interpolating an array
  argument into a string (e.g. filter('x IN ?', [1,2,3]))
* You must pass an explicit table alias argument to join_table and
  related methods, you can no longer include the table alias
  inside the table argument.
* sqlite:// URLs now operate the same as file:// URLs (2 slashes
  for a relative path, 3 for an absolute path).

---

### Doc Release Notes 2.1.0 (`doc/release_notes/2.1.0.txt`)

Model Improvements
------------------

* one_to_many/many_to_many associations now support a :limit option,
  adding a limit/offset to the records returned.  This was possible
  before using a block, so it is just added for convenience.

* Associations now support a :read_only option, which doesn't create
  methods that modify the database.

* Associations now support a :graph_select option, which allows
  specifying the columns of associated models to include when using
  eager_graph.

* one_to_many associations now have a :one_to_one option.  When used
  it creates a getter and setter method similar to many_to_one.  This
  fills the same role as ActiveRecord's has_one, but it is
  implemented as a couple of convenience methods over one_to_many, so
  it still requires that you specify the association name as a
  plural.

* Model datasets now have to_hash augmented so that it can be called
  without any arguments, in which case it yields an identity map (a
  hash with keys being primary key values and values being model
  instances).

* The Model.set_sti_key method was added, for easily setting up
  single table inheritance.  It should be called only in the parent
  class.

* Calls to def_dataset_method with a block are now cached and
  reapplied to the new dataset if set_dataset is called afterward,
  or in a subclass.

* All validation methods can now be made conditional via an :if
  option, which takes either a symbol (which specifies an instance
  method) or a proc (which is instance_evaled).

* Model#set and Model#update have been added back, they are now
  aliases of #set_with_params and #update_with_params.

* Models now have set_only/set_except/update_only/update_except
  instance methods that take a hash (like you would provide to
  set or update) and additional arguments specifying which columns
  to allow or disallow.

* Models now have a set_allowed_columns and set_restricted_columns
  methods, which operate similarly to ActiveRecord's attr_accessible
  and attr_protected.  It is recommend that you use the set_only or
  update_only instead of these methods, though.  You can ignore the
  allowed or restricted columns by using #set_all or #update_all.

* The primary key column(s) is restricted by default. To allow it to
  be set via new/set/update, use:

    Sequel::Model.unrestrict_primary_key # Global
    Artist.unrestrict_primary_key # Per Class

* It is now easy to override the one_to_many/many_to_many association
  methods that modify the database (add_/remove_/remove_all_), as
  they have been broken into two methods, one that handles the
  caching features and a private one (prepended with an _) that
  handles the database changes (and which you can easily override
  without worrying about the caching).

Table Joining
-------------

Dataset#join_table got a nice overhaul.  You can now use any join
type your database allows:

  DB[:artist].join_table(:natural, :albums)
  DB[:numbers].join_table(:cross, :numbers)

You can now specify the conditions as

* String: "a.b = c.d" # ON a.b = c.d
* Expression :x < :y # ON x < y
* Array of Symbols: [:x, :y, :z] # USING (x, y, z)
* nil # no conditions, used for NATURAL or CROSS joins

Dataset#join_table also takes a block that yields three arguments:

* join_table_alias - The alias/name of the table currently being
  joined
* last_join_table_alias - The alias name of the last table joined
  (if there was one) or the first FROM table (if not).
* joins - An array of JoinClause objects for all previous joins in
  the query.

Using the block you can specify conditions for complex joins without
needing to know in advance what table aliases will be used.

Expanded SQL Syntax Support
---------------------------

SQL Case statements are now supported directly using hashes or
arrays:

  {:x > 1 => 1}.case(0)
  # CASE WHEN x > 1 THEN 1 ELSE 0 END
  [[{:x=>1}, 0], [:x < 1, 1], [:x > 1, 2]].case(-1)
  # CASE WHEN x = 1 THEN 0 WHEN x < 1 THEN 1 WHEN x > 1 THEN 2
    ELSE -1 END

You should use an array instead of a hash for multiple conditions
unless all conditions are orthogonal.

The SQL extract function has special syntax:

  EXTRACT(day FROM date)

This syntax is now supported via the following ruby code:

  :date.extract(:day)

Other Notable Changes
---------------------

* The sequel command line tool can now run migrations.  The -m
  option specifies the directory holding the migration files,
  and the -M options specifies the version to which to migrate.

* The PostgreSQL adapter supports nested transactions/savepoints.

* The schema parser now understands decimal fields, and will
  typecast to BigDecimal.

* PostgreSQL's numeric type is now recognized and returned as
  BigDecimal.

* HAVING now comes before ORDER BY, which most databases seem to
  prefer.  If your database wants HAVING after ORDER BY, please
  let us know.

* Symbol#qualify now exists, to specify the table name for a given
  symbol, similar to the use of #as to specify an alias.  This is
  mainly helpful in conjunction with the #join_table block, as that
  provides the table aliases to use to qualify the columns inside
  the block.

* BitwiseMethods (&, |, ^, ~, <<, >>) have been added to the
  NumericExpression class, so you can do the following:

  (x + 1) ^ 10  # SQL: (x + 1) ^ 10
  ~(x + 1) # SQL: ~(x + 1)

  Usually, &, |, and ~ operate in a logical manner, but for
  NumericExpressions, they take on their usual bitwise meaning,
  since logical operations only make sense for booleans.

* #cast_numeric and #cast_string exist for Symbols, Strings, and
  other Sequel Expressions, which return the results casted and
  wrapped in either NumericExpression or StringExpression, so you
  can use the BitwiseMethods (&, |, ^, ~, <<, >>) or
  StringConcatenationMethods (+) directly.

# Dataset#to_hash can take only one argument, in which case it uses
  that argument to specify the key, and uses the entire hash for the
  value.

# Dataset#graph can now take an array of columns to select from the
  joined table via the :select option.

# Dataset#filter and similar methods now combine the block and
  regular argument conditions if both are given, instead of ignoring
  the regular argument conditions.

# Dataset#filter(false) can now be used to make sure that no records
  are returned.  Dataset#filter(true) also works, but it's a no-op.
  Before, these raised errors.

# Dataset#count does a subquery for a dataset using DISTINCT, since
  the otherwise it would yield a count for the query without
  DISTINCT.

ParseTree Support Officially Deprecated
---------------------------------------

The support for ParseTree-based block filters has officially been
deprecated and will be removed in Sequel 2.2.  To use the
expression filters (which don't require ParseTree) inside blocks,
use:

  SEQUEL_NO_PARSE_TREE = true
  require 'sequel'
  # OR
  require 'sequel'
  Sequel.use_parse_tree = false

This is the default if ParseTree cannot be loaded.  If ParseTree
can be loaded, it remains the default, in order not to immediately
break existing code.

With this set, you can use the expression filters inside of blocks:

  dataset.filter{((:x + 1) & 10 < :y) & :z}

That doesn't gain you all that much, but there are some methods
that feed block arguments into filter, such as the following:

  dataset.first(5){((:x + 1) & 10 < :y) & :z}

Which will get you the first 5 records matching the condition.

Backwards Incompatible Changes
------------------------------

* To change the datetime class used from Time to DateTime, you
  now use:

    Sequel.datetime_class = DateTime # instead of Sequel.time_class

* Models now raise errors if you try to access a missing or
  restricted method via new/set/update, instead of just silently
  skipping that parameter.  To get the old behavior:

    Sequel::Model.strict_param_setting = false

* The association_dataset method now takes into account the :eager
  option and the block argument, where it didn't before. It also
  takes into account the new :limit option.

* Association methods now raise errors in most cases if the model
  doesn't have a valid primary key.

* Dataset#join_table used to allow a symbol as a conditions argument
  as a shortcut for a hash:

    DB[:artist].join(:albums, :artist_id)
    # ON albums.artist_id = artists.id

  With the changes to #join_table, this no longer works.  It would
  now be interpreted as a boolean column:

    DB[:artist].join(:albums, :artist_id)
    # ON artists.id

  Use the following slightly longer version for the old behavior:

    DB[:artist].join(:albums, :artist_id=>:id)
    # ON albums.artist_id = artists.id

* MySQL users need to be careful when upgrading, the following code
  will once again cause an error:

    DB[:artists].each{|artist| DB[:albums].each{|album| ...}}

  To fix it, change the code to:

    DB[:artists].all{|artist| DB[:albums].each{|album| ...}}

  The issue is the MySQL adapter doesn't release the database
  connection while running each, and the second call to each gets the
  same database connection (while the other query is still running),
  because it is in the same thread.  Using #all for the outside query
  ensures that the database connection is released before the block is
  called.

  The reason for this change was that the workaround provided for
  MySQL could potentially cause issues with transactions for all
  adapters.

* String#asc and String#desc are no longer defined, as ordering on a
  plain string column should be a no-op.  They are still defined
  on LiteralStrings.

* You can no longer abuse the SQL::Function syntax to use a table
  alias with specified columns (e.g. :table[:col1, :col2, :col3])
  or to cast to types (e.g. :x.cast_as(:varchar[20])).  Use a
  LiteralString in both cases.

---

### Doc Release Notes 2.10.0 (`doc/release_notes/2.10.0.txt`)

New Supported Adapters and Databases
------------------------------------

* A DataObjects adapter was added that supports PostgreSQL,
  MySQL, and SQLite.  DataObjects is the underlying database
  library used by DataMapper, and has potential performance
  advantages by doing all typecasting in C.

* A Firebird Adapter was added, it requires the modified Ruby
  Fb adapter found at http://github.com/wishdev/fb.

* An H2 JDBC subadapter was added, based on the code used in JotBot.
  H2 is an embeddable Java database, and may be preferable to using
  SQLite on JDBC because SQLite requires native code.

New Core Features
-----------------

* Sequel now has database independent migrations.  Before, column
  types in migrations were not translated per database, so it was
  difficult to set up a migration that worked on multiple databases.
  Sequel now accepts ruby classes as database types, in addition to
  symbols and strings.  If a ruby class is used, it is translated
  to the most appropriate database type.  Here is an example using
  all supported classes (with Sequel's default database type):

    DB.create_table(:cats) do
      primary_key :id, :type=>Integer # integer
      String :a                       # varchar(255)
      column :b, File                 # blob
      Fixnum :c                       # integer
      foreign_key :d, :other_table, :type=>Bignum # bigint
      Float :e                        # double precision
      BigDecimal :f                   # numeric
      Date :g                         # date
      DateTime :h                     # timestamp
      Time :i                         # timestamp
      Numeric :j                      # numeric
      TrueClass :k                    # boolean
      FalseClass :l                   # boolean
    end

  Type translations were tested on the PostgreSQL, MySQL, SQLite,
  and H2 databases.  The default translations should work OK for
  most databases, but there will probably be a type or two that
  doesn't work.  Please send in a patch if Sequel uses a column type
  that doesn't work on your database.

  Note that existing migrations still work fine, in most cases.  If
  you were using strings or symbols for types before, they should
  still work.  See the Backwards Compatibility section below for
  details.

  Also note that this doesn't relate solely to migrations, as any
  database schema modification method that accepts types will
  accept one of the above classes.

* A ton of internal work was done to better support databases that
  fold unquoted identifiers to uppercase (which is the SQL standard).
  Sequel now allows you to set a method to call on identifiers going
  both into and out of the database.  The default is to downcase
  identifiers coming out, and upcase identifiers going in, though
  this is overridden by the PostgreSQL, MySQL, and SQLite adapters
  to not do anything (since they fold to lowercase by default).

  The settings are called identifier_input_method and
  identifier_output_method, and like most Sequel settings, they can
  be set globally, per database, or per dataset:

    # Global (use uppercase in ruby and lowercase in the database)
    Sequel.identifier_input_method = :downcase
    Sequel.identifier_output_method = :upcase
    # Per Database (use camelized names in the database, and
    #               underscored names in ruby)
    DB.identifier_input_method = :camelize
    DB.identifier_output_method = :underscore
    # Per Dataset (obfuscate your database columns!)
    class String; def rot_13; tr('A-Za-z', 'N-ZA-Mn-za-m') end end
    ds = DB[:table]
    ds.identifier_input_method = :rot_13
    ds.identifier_output_method = :rot_13

* Schema parsing support was added to the JDBC adapter, using the
  JDBC metadata methods.  This means that models that use the
  JDBC adapter will typecast data in their column setters and
  automatically select the correct primary key column(s).  This is
  currently the only adapter that supports schema parsing when using
  an MSSQL or Oracle database.

* Database#create_table now takes options, which you can use to
  specify a MySQL engine, charset, and/or collation.  You can also
  set a default engine, charset, and collation for MySQL to use:

    Sequel::MySQL.default_engine = 'InnoDB'
    Sequel::MySQL.default_charset = 'utf8'
    Sequel::MySQL.default_collate = 'utf8'

  The defaults will be used if the options are not provided.  If a
  default engine is set, you can specify :engine=>nil to not use it
  (same goes for charset and collate).

* The Sequel::DatabaseConnectionError exception class was added.  It
  is raised by the connection pool if there is an error attempting
  to instantiate a database connection.  Also, if the adapter returns
  nil instead of raising an error for faulty connection parameters,
  DatabaseConnectionError will be raised immediately, instead of the
  connection pool busy waiting until if gives up with a
  PoolTimeoutError.

* Database#tables is now supported on the JDBC adapter, returning
  an Array of table name symbols.

* Sequel now converts the following Java types returned by the JDBC
  adapter into ruby types: Java::JavaSQL::Timestamp,
  Java::JavaSQL::Time, Java::JavaSQL::Date,
  Java::JavaMath::BigDecimal, and Java::JavaIo::BufferedReader.

* When using the PostgreSQL adapter with the postgres-pr driver,
  Sequel will use a custom string escaping routine unless
  force_standard_strings = false.  This means that using Sequel's
  defaults, postgres-pr will correctly escape strings now.

* The SQLite adapter now returns float, real, and double precision
  columns as Floats.

* The SQLite adapter logs beginning, committing, and rolling back
  transactions.

* Sequel now has an internal version (before, the only way to tell
  the version was to look at the gem being used).  It is accessible
  at Sequel.version.

New Model Features
------------------

* A new validates_not_string validation was added for Sequel Models.
  It is intended to be used with the raise_on_typecast_failure =
  false setting.  In this case, for a non-string database column,
  if there is a string value when the record is going to be
  saved, it is due to the fact that Sequel was not able to typecast
  the given data correctly (so it is almost certainly not valid).
  This should make Sequel easier to use with web applications.

* An :allow_missing validation option was added to all standard
  validations.  This option skips the validation if the attribute
  is not in the object's values.  It is different from :allow_nil,
  which will skip the value if it is present but nil in the values.
  The intended use case for this option is when the database provides
  a good default.  If the attribute is not present in values, the
  database will use its default.  If the attribute is present in
  the values but equals nil, Sequel will attempt to insert it into
  the database as a NULL value, instead of using the database's
  default.  If you don't want Sequel to insert a NULL value in the
  database, but you want the database to provide the default, this
  is the option to use.

* validates_each now accepts :allow_nil and :allow_blank options,
  so it is easier to create custom validations with the same options
  as the standard validations.

* Before_* hooks now run in the reverse order that they were added.
  The purpose of hooks is to wrap existing functionality, and making
  later before_* hooks run before previous before_* hooks is the
  correct behavior.

* You can now add you own hook types, via Model.add_hook_type.  This
  is intended for plugin use.  All of the standard hooks are now
  implemented using this method.

* The value of new? in a after_save hook now reflects the
  previous state of the model (so true for a create and false for an
  update), instead of always being false.  This makes it easier
  to have a complex after_save hook that still needs to
  differentiate between a newly created record and an updated record,
  without having to add separate after_create and after_update
  hooks.

* The value of changed_columns in an after_update hook now reflects
  the value before the update occurred, instead of usually being
  empty.  Previously, to have this functionality, you generally had
  to save the value to an instance variable in a before_update hook
  so you could reference it in the after_update hook.

Other Improvements
------------------

* Sequel now longer overwrites the following Symbol instance methods
  when running on ruby 1.9: [], <, <=, >, and >=.  One of Sequel's
  principals is that it does not override methods defined by ruby,
  and now that ruby 1.9 defines the above methods on Symbol, Sequel
  shouldn't be overwriting them.

  Sequel already provides a way to work around this issue when
  another library adds the same methods to Symbol that Sequel does.
  For example, you need to change the following:

    dataset.filter(:number > 1)
    dataset.filter(:number >= 2)
    dataset.filter(:name < 'M')
    dataset.filter(:name <= 'I')
    dataset.filter(:is_bool[:x])

  To:

    dataset.filter{|o| o.number > 1}
    dataset.filter{|o| o.number >= 2}
    dataset.filter{|o| o.name < 'M'}
    dataset.filter{|o| o.name <= 'I'}
    dataset.filter{|o| o.is_bool(:x)}

  The argument provided to the block is a Sequel::SQL::VirtualRow.
  This class uses method_missing so that any methods called on it
  return Sequel::SQL::Identifiers (if no arguments are provided)
  or Sequel::SQL::Function (if arguments are provided).

  If you were using one of the above symbol methods outside of a
  filter, you can to call sql_string, sql_number, or sql_function
  on the symbol.  So the following would also work:

    dataset.filter(:number.sql_number > 1)
    dataset.filter(:number.sql_number >= 2)
    dataset.filter(:name.sql_string < 'M')
    dataset.filter(:name.sql_number <= 'I')
    dataset.filter(:is_bool.sql_function(:x))

  Using the block argument makes for a nicer API, though, so I
  recommend using it when possible.

  Note that if you are running ruby 1.8 or jruby without the --1.9
  flag, you don't need to worry.  If you are running ruby 1.9 or
  jruby --1.9, or you plan to at some point in the future, you
  should inspect your code for existing uses of these methods.
  Here are a couple command lines that should find most uses:

    # Find :symbol[]
    egrep -nr ':['\''"]?[a-zA-Z_0-9]*['\''"]?\[' *
    # Find :symbol (<|>|<=|>=)
    egrep -nr '[^:]:['\''"]?[a-zA-Z_0-9]*['\''"]? *[<>]=?' *

* Database#quote_identifiers now affects future schema modifications
  when using the database.  Previous, it only affected future
  schema modifications if a schema modification method had not yet
  been called.

* Literalization of Times and DateTimes is now correct when using the
  MySQL JDBC subadapter.

* Literalization of Blobs is now correct when using the PostgreSQL
  JDBC subadapter.

* Index and table names are quoted when creating indices in the
  PostgreSQL adapter.

* Dataset#delete was changed in the SQLite adapter to add a
  where clause that is always true, instead of doing an explicit
  count first and the deleting.  This is simpler, though it
  could potentially have performance implications.

* The sequel command line tool now supports symbol keys and unnested
  hashes in YAML files, so it should work with Merb's database.yml.
  It also includes the error class in the case of an error.

* The integration type tests were greatly expanded.  Generally,
  running the integration tests is a good way to determine how well
  your database is supported.

* Dataset#quote_identifier now returns LiteralStrings as-is, instead
  of treating them as regular strings.

* Sequel no longer modifies the MySQL::Result class when using the
  MySQL adapter.

Backwards Compatibility
----------------------

* If you were previously using a database that returned uppercase
  identifiers, it will probably return lowercase identifiers by
  default now.  To get back the old behavior:

    DB.identifier_output_method = nil

* The module hierarchy under Sequel::SQL has changed.  Now,
  modules do not include other modules, and the following modules
  were removed since they would have been empty after removing
  the modules they included: Sequel::SQL::SpecificExpressionMethods
  and Sequel::SQL::GenericExpressionMethods.

* Sequel no longer assumes the public schema by default when
  connecting to PostgreSQL.  You can still set the default
  schema to use (even to public).

* The ability to load schema information for all tables at once
  was removed from the PostgreSQL adapter.  While it worked, it had
  some issues, and it was difficult to keep it working when some
  new features were used.  This ability wasn't exposed to the user,
  and was purely an optimization.  If you have any code like:

    DB.schema

  by itself after the Database object was instantiated, you should
  remove it.

* The Database#primary_key API changed in the PostgreSQL shared
  adapter, it now accepts an options hash with :server and :conn keys
  instead of a server symbol.  Also, quite a few private Database
  instance methods changed, as well as some constants in the
  AdapterMethods.

* It is possible that some migrations will break, though it is
  unlikely.  If you were using any of the classes mentioned above
  as a method inside a migration, it might be broken.  However,
  since String, Float, and Integer wouldn't have worked as methods
  before, it is unlikely that anyone used this.

* The meaning of #String, #Integer, and #Float inside
  Sequel::SQL::Generator (i.e. inside a Database#create_table
  block) has changed.  Before, these used to call private Kernel
  methods, now, they set up columns with the appropriate database
  type.

* The Database#lowercase method in the DBI adapter was removed,
  as its use case is now met by the identifier_output_method support.

* Database#uri is now aliased explicitly via a real method, to
  allow for easier subclassing.

* You can no longer pass nil as the second argument to
  Database#create_table.

---

### Doc Release Notes 2.11.0 (`doc/release_notes/2.11.0.txt`)

Optimizations
-------------

* Model.[] was optimized to use static SQL in cases where doing so
  should result in the same output.  This should result in a 30-40%
  performance increase.  Since this can be the most significant or
  only method call in a web application action, this has potential
  to significantly enhance the performance of web application code.
  
  In order for this optimization to have an effect, you need to
  make sure that you are calling set_dataset with a Symbol and
  not a Dataset object:
  
    # Optimized:
    class Foo < Sequel::Model; end
    class Foo < Sequel::Model(:foos); end
    class Foo < Sequel::Model
      set_dataset :foos
    end
    
    # Not Optimized, but otherwise equivalent:
    class Foo < Sequel::Model(Model.db[:foos]); end
    class Foo < Sequel::Model
      set_dataset db[:foos]
    end
  
* Dataset#literal was refactored for performance reasons to make
  overriding it in subclasses unnecessary.  The changes made result
  in a 20-25% performance increase.  Sequel can spend about 10% of
  it's time in Dataset#literal, so this may be only a 2% overall
  performance improvement.

New Features
------------

* Association datasets now know about the model objects that created
  them, as well as the related association reflection.  This makes
  association extensions much more powerful.  For example, you can
  now create generic association extensions such as:
  
    module FindOrCreate
      def find_or_create(vals)
        first(vals) || association_reflection.associated_class. \
         create(vals.merge(association_reflection[:key]=> \
           model_object.id))
      end
    end
    
  The above will work for any standard one_to_many association:
  
    Artist.one_to_many :albums, :extend=>FindOrCreate
    # Create an album named Foo related to this artist,
    # unless such an album already exists
    Artist.first.albums_dataset.find_or_create(:name=>'Foo')
    
  Before, the only way to do the above was to use a closure inside
  the :dataset option proc, which couldn't be done generically
  for multiple associations.
  
* A :conditions association option was added, which allows simple
  filters to be set up without defining :graph_conditions and
  an association block:
  
    # 2.10.0
    one_to_many(:japanese_verses, :class=>:Verse, \
     :graph_conditions=>{:languageid=>3})do |ds|
       ds.filter(:languageid=>3)
    end
    # 2.11.0
    one_to_many(:japanese_verses, :class=>:Verse, \
       :conditions=>{:languageid=>3})

* A :clone association option was added, which allows you to clone
  an existing association.  This is most useful when you are dealing
  with a legacy schema and had to define the same options redundantly
  for each type of association. You can now do:
  
    many_to_many :deputies, :class=>:Employee, \
     :join_table=>:employeecurrentaudits, :left_key=>:currentauditid, \
     :right_key=>:employeeid, :order=>[:firstname, :lastname] do |ds|
      ds.filter(:active).filter(:capacity=>1)
    end
    many_to_many :project_managers, :clone=>:deputies do |ds|
      ds.filter(:active).filter(:capacity=>2)
    end
    many_to_many :team_leaders, :clone=>:deputies do |ds|
      ds.filter(:active).filter(:capacity=>3)
    end
    
  All of the above would use the same :class, :join_table, :left_key,
  :right_key, and :order options.  If you don't provide an
  association block, but you are cloning an association that has one,
  the cloned association's block is used.  You can use the
  :block=>nil option to not use a block even if the cloned
  association has a block.

* Dataset#select, #select_more, #order, #order_more, and #get all
  take a block that yields a Sequel::SQL::VirtualRow instance,
  similar to the behavior of filter. This allows for the easier
  use of SQL functions on Ruby 1.9:
  
    # 2.10.0
    dataset.select(:prettify.sql_function(:name))
    # 2.11.0
    dataset.select{|o| o.prettify(:name)}

* String#lit can now accept arguments and return an SQL literal
  string.  This allows you to do things that were previously hard
  or at least unnecessarily verbose.  For example, you can now
  easily use the SQL standard SUBSTRING function:
  
    column = :user
    pattern = params[:pattern]
    dataset.select{|o| o.substring('? from ?'.lit(column, pattern))}
    
* A validates_inclusion_of validation method was added to Model. You
  can provide a Range or an Array in the :in option to specify the
  allowed values:
  
    validates_inclusion_of :value, :in=>1..5
    validates_inclusion_of :weekday, :in=>%w'Monday Tuesday ...'

* Dataset#with_sql was added, which returns a copy of the dataset
  with static SQL.  This is useful if you want to keep the same
  row_proc/graph/transform/etc., but want to use your own custom
  SQL.

Other Improvements
------------------

* You can now use Sequel's database independent types when casting:

    dataset.select(:number.cast(String))
  
  Among other things, the default cast types for cast_string and
  cast_numeric now work in the MySQL adapter.

* Model#set_associated_object was added.  The many_to_one association
  setter method calls it.  This allows you to easily override the
  association setters for all many_to_one associations of a class
  by modifying a single method. 
  
* Typecasting invalid date strings now raises a
  Sequel::Error::InvalidValue instead of an argument error, which
  means that you can use raise_on_typecast_failure = false and not
  have an error raised when an invalid date format is used.
  
* String#to_sequel_blob was added and should now be used instead
  of String#to_blob.  sqlite3-ruby defines String#to_blob
  differently, which could cause problems.
  
* Blob columns are now fully supported in the SQLite adapter, with
  the hex escape syntax being used for input, and returning columns
  of type Sequel::SQL::Blob on output.
  
* The SQLite adapter drop_column support is now significantly more
  robust.
  
* The SQLite adapter now supports rename_column.
  
* The MySQL adapter now supports stored procedures with multiple
  arguments.
  
* The MySQL adapter can now not use a compressed connection to the
  server via the :compress=>false option.
  
* The MySQL adapter now sets a default timeout of 30 days to the
  database connection, you can change it via the :timeout option,
  which accepts a number of seconds.
  
* The MySQL adapter now sets SQL_AUTO_IS_NULL to false by default,
  you can use the :auto_is_null=>true option to not do this.
  
* The MySQL adapter now sets the encoding option on the database
  connection itself, so it works across reconnects.

* Sequel itself no longer uses String#lit or Symbol#* internally, so
  it shouldn't break if another library defines them.

* The default index name is now generated correctly if a non-String
  or Symbol column is used.
  
* Some ruby -w warnings have been fixed.

* INSERTs are now sent to the master database instead of the slave
  database(s) if using a master/slave database configuration and
  PostgreSQL 8.2+ or Firebird.
  
* DateTime literalization has been fixed in the Firebird adapter.
  
* Date literalization has been fixed in the H2 JDBC subadapter.
  
* Release notes for versions from 1.0 to the present are now included
  in the Sequel repository and the RDoc documentation, see
  http://sequel.rubyforge.org/rdoc/files/doc/release_notes/

Backwards Compatibility
----------------------

* The optimization of Model.[] may break if you modify the model's
  dataset behind its back.  Always use Model.set_dataset if you
  want to change a Model's dataset.
  
* Sequel::Dataset::UnsupportedExceptIntersect and
  Sequel::Dataset::UnsupportedExceptIntersectAll will now only be
  defined if you are using an adapter that requires them.
  
* The private Model#cache_delete_unless_new method has been removed.

* Sequel::SQL::IrregularFunction was removed, as it was a bad hack
  that is not used by Sequel anymore.  Unless you were instantiating
  it directly or using a plugin/extension that did, this shouldn't
  affect you.  Using a Sequel::SQL::Function with a 
  Sequel::SQL::PlaceholderLiteralString is recommended instead, see
  the substring example above.

---

### Doc Release Notes 2.12.0 (`doc/release_notes/2.12.0.txt`)

Overview
--------

Sequel 2.12 is really just a stepping stone to Sequel 3.0, which will
be released next month.  All major changes currently planned for 3.0
have been made in 2.12, but 2.12 contains many features that have
been deprecated and will be removed or moved into extensions or
plugins in 3.0.

Deprecation Logging
-------------------

If you use a deprecated method or feature, Sequel will by default
print a deprecation message and 10 lines of backtrace to standard
error to easily allow you to figure out which code needs to be
updated.  You can change where the deprecation messages go and how
many lines of backtrace are given using the following:

  # Log deprecation information to a file
  Sequel::Deprecation.output = File.open('deprecated.txt', 'wb')
  
  # Use 5 lines of backtrace when logging deprecation messages
  Sequel::Deprecation.backtraces = 5
  
  # Use all backtrace lines when logging deprecation messages
  Sequel::Deprecation.backtraces = true
  
  # Don't include backtraces in the deprecation logging
  Sequel.Deprecation.backtraces = false
  
  # Turn off all deprecation logging
  Sequel::Deprecation.output = nil

Deprecated Features Moving to Extensions
----------------------------------------

* Migrations are being moved into sequel/extensions/migration.  There
  isn't any reason that they should be loaded in normal use since
  they are used so rarely.  The sequel command line tool uses this
  extension to run the migrations.
  
* Adding the blank? method to all objects has been moved into
  sequel/extensions/blank.
  
* Dataset#print and Sequel::PrettyTable have been moved into
  sequel/extensions/pretty_table.
  
* Dataset#query and related methods have been moved into
  sequel/extensions/query.
  
* Dataset#paginate and related methods have been moved into
  sequel/extensions/pagination.
  
* String inflection methods (e.g. "people".singularize) have been
  moved into sequel/extensions/inflector.
  
* String date/time conversion methods (e.g. '2000-01-01'.to_date)
  have been moved into sequel/extensions/string_date_time.

Deprecated Model Features Moving to Plugins
-------------------------------------------

* Model validation class methods have been moved to a plugin.  Sequel
  users are encouraged to write their own validate instance method
  instead. A new validation_helpers plugin has been added to make
  this easier, it's explained in the New Features section.  If you
  want to continue using the validation class methods:
  
    Sequel::Model.plugin :validation_class_methods
  
* Model hook class methods have been moved to a plugin.  Sequel users
  are encouraged to write their own hook instance methods, and call
  super to get hooks specified in superclasses or plugins.  If you
  want to continue using the hook class methods:
  
    Sequel::Model.plugin :hook_class_methods
  
* Model schema methods (e.g. Model.set_schema, Model.create_table, 
  Model.drop_table) have been moved to a plugin.  The use of these
  methods has been discouraged for a long time.  If you want to use
  them:
  
    Sequel::Model.plugin :schema

* Model.set_sti_key has been moved to a plugin.  So you should
  change:

    MyModel.set_sti_key :key_column

  to:
  
    MyModel.plugin :single_table_inheritance, :key_column
    
* Model.set_cache has been moved to a plugin.  So you should change:

    MyModel.set_cache cache_store, opts
    
  to:
  
    MyModel.plugin :caching, cache_store, opts
    
* Model.serialize has been moved to a plugin.  So you should change:

    MyModel.serialize :column, :format=>:yaml
    
  to:
  
    MyModel.plugin :serialization, :yaml, :column
    
  Because the previous serialization support depended on dataset
  transforms, the new serialization support is implemented
  differently, and behavior may not be identical in all cases.
  However, this should be a drop in replacement for most users.

Deprecated Features To Be Removed in Sequel 3.0
-----------------------------------------------

* Dataset#transform is deprecated without any replacement planned.
  It was announced on the Sequel mailing list that transforms would
  be removed unless someone said they needed them, and nobody said
  that they did.

* Dataset#multi_insert and Dataset#import are no longer aliases
  of each other.  Dataset#multi_insert now takes an array of hashes,
  and Dataset#import now takes an array of columns and an array
  of arrays of values.  Using multi_insert with import's API or
  vice-versa is deprecated.
  
* Calling Dataset#[] with no arguments or an integer argument is
  deprecated.
  
* Calling Dataset#map with both an argument and a block is
  deprecated.
  
* Database#multi_threaded? and Database#logger are both deprecated.

* Calling Database#transaction with a symbol to specify which server
  to use is deprecated.  You should now call it with an option hash
  with a :server key.
  
* Array#extract_options! and Object#is_one_of? are both deprecated.

* The metaprogramming methods taken from metaid are deprecated and
  have been moved into Sequel::Metaprogramming.  If you want them
  available to specific objects/classes, just include or extend with
  Sequel::Metaprogramming.  If you want all objects to have access to
  the metaprogramming methods, install metaid.  Note that the
  class_def method from metaid doesn't exist in
  Sequel::Metaprogramming, since it really isn't different from
  define_method (except it is public instead of private).
  
* Module#class_attr_overridable, #class_attr_reader, and
  #metaalias are deprecated.
  
* Using Model#set or #update when the columns for the model are not
  set and you provide a hash with symbol keys is deprecated.
  Basically, you must have setter methods now for any columns used in
  #set or #update.
  
* Model#set_with_params and #update_with_params are deprecated, use
  #set and #update instead.
  
* Model#save! is deprecated, use #save(:validate=>false).

* Model.is and Model.is_a are deprecated, use Model.plugin.

* Model.str_columns, Model#str_columns, #set_values, and
  #update_values are deprecated.  You should use #set and
  #update instead of #set_values and #update_values, though they
  operate differently.
  
* Model.delete_all, Model.destroy_all, Model.size, and Model.uniq
  are deprecated, use .delete, .destroy, .count, and .distinct.
  
* Model.belongs_to, Model.has_many, and Model.has_and_belongs_to_many
  are deprecated, use .many_to_one, .one_to_many, and .many_to_many.
  
* Model#dataset is deprecated, use Model.dataset.

* SQL::CastMethods#cast_as is deprecated, use #cast.

* Calling Database#schema without a table argument is deprecated.

* Dataset#uniq is deprecated, use Dataset#distinct.

* Dataset#symbol_to_column_ref is deprecated, use #literal.

* Dataset#quote_column_ref is deprecated, use #quote_identifier.

* Dataset#size is deprecated, use #count.

* Passing options to Dataset#each, #all, #single_record,
  #single_value, #sql, #select_sql, #update, #update_sql, #delete,
  #delete_sql, and #exists is deprecated.  Modify the options first
  using clone or a related method, then call one of the above
  methods.
  
* Dataset#create_view and #create_or_replace_view are deprecated,
  use the database methods instead.

* Dataset.dataset_classes, #model_classes, #polymorphic_key, and
  #set_model are deprecated.
  
* Database#>> is deprecated.

* String#to_blob and SQL::Blob#to_blob are deprecated, use
  #to_sequel_blob.
  
* The use of Symbol#| to create array subscripts is deprecated,
  use Symbol#sql_subscript.
  
* Symbol#to_column_ref is deprecated, use Dataset#literal.

* String#expr is deprecated, use String#lit.

* Array#to_sql, String#to_sql, and String#split_sql are deprecated.

* Passing an array to Database#<< is deprecated.

* Range#interval is deprecated.

* Enumerable#send_each is deprecated.

* When using ruby 1.8, Hash#key is deprecated.

* Sequel.open is deprecated, use Sequel.connect.

* Sequel.use_parse_tree and Sequel.use_parse_tree= are deprecated.

* All upcase_identifier methods and the :upcase_identifiers database
  option are deprecated, use identifier_input_method = :upcase
  instead.
  
* Using a virtual row block without an argument is deprecated, see
  Sequel.virtual_row_instance_eval= under New Features.
  
* When using the JDBC adapter, Java::JavaSQL::Timestamp#usec is
  deprecated.  Sequel has returned Java::JavaSQL::Timestamp as
  DateTime or Time for a few versions, so this shouldn't affect most
  people.
  
* Sequel will no longer require bigdecimal/util, enumerator, or yaml
  in 3.0.  If you need them in your code, make sure you require
  them yourself.  Using features added by requiring these standard
  libraries will not bring up a deprecation warning, for obvious
  reasons.
  
* Sequel::Error::InvalidTransform, Sequel::Error::NoExistingFilter,
  and Sequel::Error::InvalidStatement exceptions will be removed in
  Sequel 3.0.  You will not get a deprecation message if you reference
  them in 2.12.
  
* Sequel::Model::Validation::Errors is deprecated, use
  Sequel::Model::Errors instead.  Referencing the old name will not
  bring up a deprecation message.

New Features
------------

* Sequel.virtual_row_instance_eval= was added, which lets you give
  Sequel 2.12 the behavior that will be the standard in 3.0.
  It changes blocks passed to Dataset#filter, #select, or #order that
  don't accept arguments (or accept any number of arguments) to
  instance eval the block in the context of a new VirtualRow
  instance instead of passing a new VirtualRow instance to the block.
  It allows you to change code that looks like this:

    dataset.filter{|o| (o.number > 10) & (o.name > 'M')}

  to:

    dataset.filter{(number > 10) & (name > 'M')}

  When instance_eval is used, only local variables are available
  to the block.  Any calls to instance methods will be interpreted
  as calling VirtualRow#method_missing, which generates identifiers
  or functions.  When virtual_row_instance_eval is enabled, the
  following type of code will break:

    # amount is a instance method
    dataset.filter{:number + amount > 0}
      
  Just like this example, the only type of code that should break is
  when a virtual row block was used when it wasn't necessary (since
  it doesn't use the VirtualRow argument).
  
  When Sequel.virtual_row_instance_eval = false, using a virtual row
  block that doesn't accept an argument will cause a deprecation
  message.
  
  Here's a regular expression that should catch most places where you
  are using a virtual row block without an argument.

    egrep -nr '[^A-Za-z0-9_](filter|select|select_more|order|order_more|get|where|having|from|first|and|or|exclude|find|subset|constraint|check)( *(\([^)]*\) *)?){*[^|]' *
    
  An RDoc page explaining virtual row blocks was added as well.

* A validation_helpers model plugin was added that allows you to do
  validations similar to the old class level validations inside
  the Model#validate instance method.  The API has changed, but it's
  capable of most of the same validations.  It doesn't handle
  acceptance_of or confirmation_of validations, as those shouldn't be
  handled in the model.
  
    # Old class level validations
    validates_format_of :col, :with=>/.../
    validates_length_of :col, :maximum=>5
    validates_length_of :col, :minimum=>3
    validates_length_of :col, :is=>4
    validates_length_of :col, :within=>3..5
    validates_not_string :col
    validates_numericality_of :col
    validates_numericality_of :col, :only_integer=>true
    validates_presence_of :col
    validates_inclusion_of :col, :in=>[3, 4, 5]
    validates_uniqueness_of :col, :col2
    validates_uniqueness_of([:col, :col2])

    # New instance level validations
    def validate
      validates_format /.../, :col
      validates_max_length 5, :col
      validates_min_length 3, :col
      validates_exact_length 4, :col
      validates_length_range 3..5, :col
      validates_not_string :col
      validates_numeric :col
      validates_integer :col
      validates_presence :col
      validates_includes([3,4,5], :col)
      validates_unique :col, :col2
      validates_unique([:col, :col2])
    end
    
  Another change made is to specify the same type of validation on
  multiple attributes, you must use an array:

    # Old
    validates_length_of :name, :password, :within=>3..5

    # New
    def validate
      validates_length_range 3..5, [:name, :password]
    end
    
  The :message, :allow_blank, :allow_missing, and :allow_nil options
  are still respected.  The :tag option is not needed as instance level
  validations work with code reloading without workarounds. The :if
  option is also not needed for instance level validations:

    # Old
    validates_presence_of :name, :if=>:new?
    validates_presence_of :pass, :if=>{flag > 3}

    # New
    def validate
      validates_presence(:name) if new?
      validates_presence(:pass) if flag > 3
    end
    
  The validates_each also doesn't have an equivalent instance method,
  since it is much easier to just write your own validation:
  
    # Old
    validates_each(:date) do |o,a,v|
      o.errors.add(a, '...') unless v > Date.today
    end

    # New
    def validate
      errors.add(:date, '...') unless date > Date.today
    end
    
* MySQL adapter datasets now have on_duplicate_key_update and
  insert_ignore methods which modify the SQL used to support
  ON DUPLICATE KEY UPDATE and INSERT IGNORE syntax in multi_insert
  and import.
  
* If you use the MySQL native adapter, you can set:

    Sequel::MySQL.convert_invalid_date_time = nil
    
  to return dates like "0000-00-00" and times like "25:00:00" as
  nil values instead of raising an error.  You can also set it
  to :string to return the values as strings.

* You can now use Sequel without modifying any core classes, by
  defining a SEQUEL_NO_CORE_EXTENSIONS constant or environment
  variable.  In 2.12, this may still add some deprecated methods to
  the core classes, but in 3.0 no methods will be added to the core
  classes if you use this.

* You can now use Sequel::Model without the associations
  implementation by defining a SEQUEL_NO_ASSOCIATIONS constant or
  environment variable.

Other Improvements
------------------

* Model column accessors have been made faster and the overhead of
  creating them has been reduced significantly.

* ~{:bool_col=>true} now generates an bool_col IS NOT TRUE filter
  instead of bool_col != TRUE.  This makes it return records with
  NULL values.  If you only want to have false records, you should
  use {:bool_col=>false}.  This works better with SQL's 3 valued
  boolean logic.
  
  It is slightly inconsistent with ~{:col=>1}, since that won't
  return values where col is NULL, but it gives the user the ability
  to create an IS [NOT] (TRUE|FALSE) filter, which Sequel previously
  did not support.
  
  If you really want the old behavior, you can change it to 
  ~{true=>:bool_col}.
  
* Model.use_transactions was added for setting whether model objects
  should use transactions when destroying or saving records.  Like
  most Sequel options, it's settable on a global, per model, and
  per object basis:
  
    Sequel::Model.use_transactions = false
    MyModel.use_transactions = true
    my_model.use_transactions = false
    
  You can also turn it on or off for specific save calls:
  
    my_model.save(:transaction=>true)
    
* The Oracle adapter now supports schema parsing.
    
* When using Model.db=, all current dataset options are copied to
  a new dataset created with the new db.

* Model::Errors#count was refactored to improve performance.

* Most exception classes that were located under Sequel::Error are
  now located directly under Sequel.  The old names are not
  deprecated (unless mentioned above), but their use is now
  discouraged.  The exceptions have the same name except that
  Sequel::Error::PoolTimeoutError changed to Sequel::PoolTimeout.

* Dataset#where now always affects the WHERE clause.  Before, it
  was just an alias of filter, so it modified the HAVING clause
  if the dataset already had a HAVING clause.

* The optimization of Model.[] introduced in 2.11.0 broke on
  databases that didn't support LIMIT.  The optimization now works
  on those databases.

* All of the the RDoc documentation was reviewed and many updates
  were made, resulting in significantly improved documentation
  quality.
  
* Model.def_dataset_method now works when the model doesn't have an
  associated dataset, as it will add the method to a dataset
  given to set_dataset in the future.
  
* Database#get and #select now take a block that is passed to
  the dataset they create.
  
* You can disable the use of INSERT RETURNING in the shared
  PostgreSQL adapter using disable_insert_returning.  This is mostly
  useful if you are inserting a large number of records.
  
* A bug relating to aliasing columns in the JDBC adapter has been
  fixed.

* Sequel can now create and drop schema-qualified views.
  
* Performance of Dataset#destroy for model datasets was improved.

* The specs now run on Rspec 1.2.

* Internal dependence on the methods that Sequel adds to core
  classes has been eliminated, any internal use of methods that
  Sequel adds to the core classes is now considered a bug.
  
* A possible bug where Database#rename_table would not remove a
  cached schema entry has been fixed.
  
* The Oracle and MySQL adapters now raise an error as soon as you
  call distinct on a dataset, instead of waiting until the SQL is
  generated.

Backwards Compatibility
----------------------

* Saving a newly inserted record in an after_create or after_save
  hook is no longer broken.  It broke in 2.10 as a side effect of
  allowing the hook to check whether or not the record was a new
  record.  The code has been changed so that a @was_new instance
  variable will be defined to true if the record was just created.
  
  Similarly, instead of not modifying changed_columns until after
  the after hooks run, a @columns_updated instance variable will
  be available in the after hooks that is a hash of exactly what
  attribute keys and values were used in the update.
  
  These changes break compatibility with 2.11.0 and 2.10.0, but
  restore compatibility with 2.9.0 and previous versions.
  
* PostgreSQL no longer uses savepoints for nested transactions by
  default.  If you want to use a savepoint, you have to pass the
  :savepoint option to the transaction method.  Using savepoints
  by default broke expectations when a method raised Rollback to
  rollback the transaction, and it only rolled back to the last
  savepoint.

* The anonymous model classes created by Sequel::Model() are now
  stored in Model::ANONYMOUS_MODEL_CLASSES instead of the @models
  class instance variable of the main module.
  
* The mappings of adapter schemes to classes are now stored in
  Sequel::ADAPTER_MAP instead of the Database @@adapters class
  variable.

* Model instances no longer contain a reference to their class's
  @db_schema.

* Database schema sql methods (e.g. alter_table_sql) are now private.

* Database#[] no longer accepts a block.  It's not possible to call
  it with a block in general usage, anyway.
  
* The Sequel::Schema::SQL module no longer exists, the methods it
  included were placed directly in the Sequel::Database class.

* The Sequel::SQL::SpecificExpression class has been removed,
  subclasses now inherit from Sequel::SQL::Expression.

* Sequel now requires its own files with an absolute path.

* The file hierarchy of the sequel library changed significantly.

---

### Doc Release Notes 2.2.0 (`doc/release_notes/2.2.0.txt`)

The Most Powerful and Flexible Associations of Any Ruby ORM
-----------------------------------------------------------

Sequel can now support any association type supported by
ActiveRecord, and many association types ActiveRecord doesn't
support.

Association callbacks (:before_add, :after_add, :before_remove,
:after_remove) have been added, and work for all association
types.  Each of the callback options can be a Symbol specifying an
instance method that takes one argument (the associated object), or a
Proc that takes two arguments (the current object and the associated
object), or an array of Symbols and Procs.  Additionally, an
:after_load callback is available, which is running after loading the
associated record(s) from the database.

Association extensions are now supported:

  class FindOrCreate
    def find_or_create(vals)
      first(vals) || create(vals)
    end
  end
  class Author < Sequel::Model
    one_to_many :authorships, :extend=>FindOrCreate
  end
  Author.first.authorships_dataset.find_or_create(:name=>'Bob')

Sequel has been able to support most has_many :through style
associations since 1.3, via many_to_many (since it doesn't break on
join tables that are also model tables, unlike ActiveRecord's
has_and_belongs_to_many).  Now it can also support has_many :through
style associations where it goes through a has_many association.

Sequel can now support polymorphic associations.  Polymorphic
associations are really a design flaw, so Sequel doesn't support them
directly, but the tools that Sequel gives you make them pretty easy
to implement.

Sequel can also support associations that ActiveRecord does not.  For
example, a belongs_to association where the column referenced in the
associated table is not the primary key, an association that depends
on multiple columns in each table, or even situations where the
association has a column in the primary table that can be referenced
by any of multiple columns in a second table that has a has_one style
association with the table you want to associate with.

Some of those associations can be supported for a single object using
custom SQL in ActiveRecord, but none are supported when eager
loading or allow further filtering.

Not only can all of these cases be supported with Sequel::Model, all
can be supported with eager loading, and can allow for further
filtering. See
http://sequel.rubyforge.org/files/sequel/doc/advanced_associations_rdoc.html
for details and example code for all association types covered above.

There have also been many additional options added for controlling
eager loading via eager_graph.  Every part of the SQL JOINs can now
be controlled via one of the options, so you can use JOIN USING,
NATURAL JOIN, or arbitrary JOIN ON conditions.

Finally, just to show off the power that Sequel gives you when eager
loading, here is example code that will eagerly load all descendants
and ancestors in a tree structure, without knowing the depth of the
tree:

  class Node < Sequel::Model
    set_schema do
      primary_key :id
      foreign_key :parent_id, :nodes
    end
    create_table

    many_to_one :parent
    one_to_many :children, :key=>:parent_id

    # Only useful when eager loading
    many_to_one :ancestors, :eager_loader=>(proc do |key_hash, nodes,
associations|
      # Handle cases where the root node has the same parent_id as
primary_key
      # and also when it is NULL
      non_root_nodes = nodes.reject do |n|
        if [nil, n.pk].include?(n.parent_id)
          # Make sure root nodes have their parent association set to
nil
          n.associations[:parent] = nil
          true
        else
          false
        end
      end
      unless non_root_nodes.empty?
        id_map = {}
        # Create an map of parent_ids to nodes that have that parent id
        non_root_nodes.each{|n| (id_map[n.parent_id] ||= []) << n}
        # Doesn't cause an infinite loop, because when only the root node
        # is left, this is not called.
        Node.filter(Node.primary_key=>id_map.keys).eager(:ancestors).all
do |node|
          # Populate the parent association for each node
          id_map[node.pk].each{|n| n.associations[:parent] = node}
        end
      end
    end)
    many_to_one :descendants, :eager_loader=>(proc do |key_hash, nodes,
associations|
      id_map = {}
      nodes.each do |n|
        # Initialize an empty array of child associations for each
parent node
        n.associations[:children] = []
        # Populate identity map of nodes
        id_map[n.pk] = n
      end
      # Doesn't cause an infinite loop, because the :eager_loader is not
called
      # if no records are returned.  Exclude id = parent_id to avoid
infinite loop
      # if the root note is one of the returned records and it has
parent_id = id
      # instead of parent_id = NULL.
      Node.filter(:parent_id=>id_map.keys).exclude(:id=>:parent_id).eager(:descendants).all
do |node|
        # Get the parent from the identity map
        parent = id_map[node.parent_id]
        # Set the child's parent association to the parent
        node.associations[:parent] = parent
        # Add the child association to the array of children in the
parent
        parent.associations[:children] << node
      end
    end)
  end

  nodes = Node.filter(:id < 10).eager(:ancestors, :descendants).all

New Adapter Features
--------------------

* PostgreSQL bytea fields are now fully supported.

* The PostgreSQL adapter now uses the safer connection-specific
  string escaping if you are using ruby-pg.

* The SQLite adapter supports drop_column and add_index.

* You can now use URL parameters in the connection string, enabling
  you to connect to PostgreSQL via a socket using
  postgres://user:password@blah/database?host=/tmp

Other New Features
------------------

* Dataset#graph now takes a block which it passes to join_table.

* Symbol#identifier has been added, which can be used if another
  library defines the same operator(s) on Symbol that Sequel defines.

* Filter blocks now yield a VirtualRow instance, which can yield
  Identifiers, QualifiedIdentifiers, or Functions.  Like
  Symbol#identifier, this is useful if another library defines the
  same operator(s) on Symbol that Sequel defines.

* You can now call Model.to_hash to get an identity map for all
  rows (before this required Model.dataset.to_hash).

* A model that can get it's column information from the schema will
  set it in the dataset, potentially saving many queries.

* Model.validates_presence_of now works correctly for boolean
  columns.

Notable Bug Fixes
-----------------

* Caching now works with Model subclasses.

* Model validation methods now work with source reloading.

* The PostgreSQL adapter no longer raises an Error if you try to
  insert a record with the primary key already specified.

* Sequel no longer messes with the native MySQL adapter, so you can
  use Sequel and ActiveRecord with MySQL in the same process.

* Dataset#count now works correctly for limited dataset.

* PostgreSQL Database#transaction method yields a connection, similar
  to the other adapters.

* Using a hash argument in #distinct, #order, or #group is treated
  as an expression instead of a column alias.

* Cloned datasets no longer ignore the existing columns unless it is
  necessary.

* The :quote_identifiers and :single_threaded Database options now
  work correctly.

Backwards Incompatible Changes
------------------------------

* ParseTree support, deprecated in 2.1.0, has been removed in 2.2.0.
  You should use the expression filter syntax instead, preferably
  without the block (though it can be used inside a block as well).
  This usually involves the following types of changes:

    filter{:x == :y} => filter(:x => :y)
    filter{:x << :y} => filter(:x => :y)
    filter{:x && :y} => filter(:x & :y) # Don't forget about change
    filter{:x || :y} => filter(:x | :y) #  in operator precedence
    filter{:x.like?('%blah%')} => filter(:x.like('%blah%'))
    filter do => filter((:x > 1) & (:y < 2))
      :x > 1
      :y < 2
    end

* Attempts to save an invalid Model instance will raise an error by
  default.  To revert to returning a nil value, use:

    Sequel::Model.raise_on_save_failure = false # Global
    Album.raise_on_save_failure = false # Class
    album = Album.new
    album.raise_on_save_failure = false # Instance

  Note that before, save would return false where now it returns nil
  if you disable raising on save failure.

* Dataset#update no longer takes a block, as it's use of the block
  depended on ParseTree.  With the introduction of the expression
  syntax in 2.0.0, it's no longer necessary.  You should use a hash
  with an expression as the value instead:

    DB[:table].update(:column=>:column + 1)

* validates_presence of now considers false as present instead of
  absent.  This is so it works with boolean columns.

* Dataset#graph ignores any previously selected columns when it is
  called for the first time.

* Dataset#columns ignores any filtering, ordering, or distinct
  clauses.  This shouldn't cause issues unless you were using
  SQL functions with side effects and expecting them to be called
  when columns was called (unlikely at best).

One significant point of note is that the 2.2.0 release will be the
last release with both a sequel_core and sequel gem.  Starting
with 2.3.0 they will be combined into one sequel gem.  You will still
be able to get just the sequel_core part by requiring 'sequel_core',
but they will be packaged together.

---

### Doc Release Notes 2.3.0 (`doc/release_notes/2.3.0.txt`)

JRuby and Ruby 1.9 Officially Supported
---------------------------------------

Sequel now officially supports JRuby 1.1.3 and Ruby 1.9 (svn revision
18194 at least).  Using JRuby with the JDBC adapter, PostgreSQL,
MySQL, and SQLite now enjoy almost full support, though not
everything works the same as using the native adapter.  Depending on
what you are doing, it may make sense to use postgres-pr on JRuby
instead of PostgreSQL-JDBC.

To use the new JDBC support, the database connection string you give
Sequel is now passed directly to JDBC, here are a few examples:

  Sequel.connect('jdbc:postgresql://host/database?user=*&password=*')
  Sequel.connect('jdbc:mysql://host/database?user=*&password=*')
  Sequel.connect('jdbc:sqlite::memory:')
  Sequel.connect('jdbc:sqlite:relative/path.db')
  Sequel.connect('jdbc:sqlite:/absolute/path.db')

Single Gem
----------

Sequel is now distributed as a single gem named sequel, by combining
the previous sequel_core and sequel gems.  You can still just
"require 'sequel_core'" if you don't want the model functionality.

Database Adapter Improvements
-----------------------------

* Dataset#empty? now works using the MySQL adapter.

* The Oracle adapter now works with a nonstandard database port.

* The JDBC adapter should load JDBC drivers automatically for
  PostgreSQL, MySQL, SQLite, Oracle, and MSSQL.  For PostgreSQL,
  MySQL, and SQLite, the jdbc-* gem can be used, for the others, you
  must have the correct .jar in your CLASSPATH.

* The PostgreSQL adapter no longer raises an error when inserting
  records into a table without a primary key.

* Database#disconnect now works for the ADO adapter.

* The ADO adapter no longer raises an error if the dataset contains
  no records.

* The ODBC adapter no longer errors when converting ::ODBC::Time
  values.

Backwards Incompatible Changes
------------------------------

* Sequel::Worker has been removed.  There are no known users, and the
  specs caused problems on JRuby.

* Assigning an empty string to a non-string, non-blob model attribute
  converts it to nil by default.  You can use
  "Model.typecast_empty_string_to_nil = false" to get the old
  behavior.  This should make web development with Sequel
  significantly easier, hopefully at no expense to other uses.

* Database.uri_to_options is now a private class method.

* Model.create_table! now acts the same as Database.create_table!,
  dropping the table unconditionally and then creating it.  This was
  done for consistency.  If you are using Model.create_table! in
  production code, you should change it to
  "Model.create_table unless Model.table_exists?", otherwise you risk
  wiping out your production data.  I recommended you use the
  migration feature instead of Model.set_schema, as that handles
  altering existing tables.

Other Notable Changes
---------------------

* Using validates_length_of more than once on the same attribute with
  different options without a tag no longer causes the first use to
  be ignored.  This was a side effect of the validation tags added
  in 2.2.0.

* Other than the adapters, Sequel now has 100% code coverage (line
  coverage).

* Model#set* methods now return self.

* An integration test suite was added, testing Sequel against a live
  database with nothing mocked, which helped greatly when testing the
  new support for JDBC adapters.

---

### Doc Release Notes 2.4.0 (`doc/release_notes/2.4.0.txt`)

Prepared Statements/Bound Variables
===================================

Sequel now supports prepared statements and bound variables.  No
matter which database you are using, Sequel uses exactly the same API.
To specify placeholders, you use the :$placeholder syntax:

  ds = DB[:items].filter(:name=>:$n)

To use a bound variable:

  ds.call(:select, :n=>'Jim')

This will do the equivalent of selecting records that have the name
'Jim'.  In addition to :select, you can use :first or :delete. There
is also support for bound variables when inserting or updating
records:

  ds.call(:update, {:n=>'Jim', :new_n=>'Bob'}, :name=>:$new_n)

Which will update all records that have the name 'Jim' to have the
name 'Bob'.

Prepared statement support is very similar to bound variable support,
except that the statement is first prepared with a name:

  ps = ds.prepare(:select, :select_by_name)

It is then called later with the bound arguments to use:

  ps.call(:n=>'Jim')
  DB.call(:select_by_name, :n=>'Jim') # same as above

For inserting or updating, the hash to use when inserting or updating
is given to prepare:

  ps2 = ds.prepare(:update, :update_name, :name=>:$new_n)
  ps2.call(:n=>'Jim', :new_n=>'Bob')

There is some level of native support for these features in the
PostgreSQL, MySQL, SQLite, and JDBC adapters.  For other adapters,
support is emulated, but it shouldn't be too difficult to add native
support for them.

For more details see:
http://sequel.rubyforge.org/rdoc/files/doc/prepared_statements_rdoc.html

Read-Only Slave/Writable Master and Database Sharding
=====================================================

Sequel now has built in support for master/slave database
configurations, just by setting an option in Sequel.connect:

  DB=Sequel.connect('postgres://master_server/database', \
    :servers=>{:read_only=>{:host=>'slave_server'}})

That will use slave_server for SELECT queries and master_server for
other queries.  It's fairly easy to use multiple slaves or even
multiple masters, examples are included in the link below.

Sharding support requires some code other than the database
configuration, but is still fairly simple.  For example, to set up
a 16 shard configuration based on a hex character:

  servers = {}
  (('0'..'9').to_a + ('a'..'f').to_a).each do |hex|
    servers[hex.to_sym] = {:host=>"hash_host_#{hex}"}
  end
  DB=Sequel.connect('postgres://hash_host/hashes', :servers=>servers)

To set which shard to use for a query, use the Dataset#server method:

  DB[:hashes].server(:a).filter(:hash=>/31337/)

For more details see:
http://sequel.rubyforge.org/rdoc/files/doc/sharding_rdoc.html

Other Changes
=============

* The sequel.rubyforge.org website has a new design thanks to boof.
  The online RDoc is now located at http://sequel.rubyforge.org/rdoc.

* Support was added for anonymous column names in the ADO adapter.

* Better MSSQL support in the ADO, ODBC, and JDBC adapters.  The
  odbc_mssql adapter has been removed. If you use MSSQL with ODBC,
  please use the odbc adapter with a :db_type=>'mssql' option.

* The following Sequel::Error exception subclasses were removed:
  InvalidExpression, InvalidFilter, InvalidJoinType, and WorkerStop.

* Documentation was added for the PostgreSQL, MySQL, SQLite, and
  JDBC adapters.

* Various internal interfaces were refactored.  For example, if you
  use an adapter not included with Sequel, it probably won't work
  until you update it to the new internal API.

* Many low level methods (such as Database#transaction), now take
  an optional server argument to indicate which server to use.

* Model plugins that have a DatasetMethods module with non-public
  methods no longer have Model methods created that call those
  methods.

---

### Doc Release Notes 2.5.0 (`doc/release_notes/2.5.0.txt`)

New Features
------------

* The values that are used to insert/update records can now be
  scoped similar to how filter expressions can be scoped.
  set_defaults is used to set defaults which can be overridden,
  and set_overrides is used to set defaults which cannot be
  overridden:

      DB[:t].set_defaults(:x=>1).insert_sql
      # => INSERT INTO t (x) VALUES (1)
      DB[:t].set_defaults(:x=>1).insert_sql(:x=>2)
      # => INSERT INTO t (x) VALUES (2)
      DB[:t].set_defaults(:x=>1).insert_sql(:y=>2)
      # => INSERT INTO t (x, y) VALUES (1, 2)
      DB[:t].set_overrides(:x=>1).insert_sql(:x=>2)
      # => INSERT INTO t (x) VALUES (1)

  The difference between set_defaults and set_overrides is that
  with set_defaults, the last value takes precedence, while with
  set_overrides, the first value takes precedence.

* The schema generators now support creating and altering tables
  with composite primary and/or foreign keys:

    DB.create_table(:items) do
      integer :id
      text :name
      primary_key [:id, :name]
      foreign_key [:id, :name], :other_table, \
        :key=>[:item_id, :item_name]
    end

    DB.alter_table(:items) do
      add_primary_key [:id, :name]
      add_foreign_key [:id, :name], :other_table, \
        :key=>[:item_id, :item_name]
    end

* The AlterTableGenerator now supports unique constraints:

    DB.alter_table(:items) do
      add_unique_constraint [:aaa, :bbb, :ccc], :name => :con3
    end

* The schema generators now support ON UPDATE (previously, they only
  supported ON DELETE):

    DB.create_table(:items) do
      foreign_key :project_id, :projects, :on_update => :cascade
    end

* When connecting to a PostgreSQL server version 8.2 and higher,
  Sequel now uses the INSERT ... RETURNING ... syntax, which should
  speed up row inserts on PostgreSQL.  In addition, Sequel Models
  use RETURNING * to speed up model object creation.

* You can now validate multiple attributes at once.  This is useful
  if the combination of two or more attribute values is important,
  such as checking the uniqueness of multiple columns.
  validates_uniqueness_of now supports this directly:

    validates_uniqueness_of [:column1, :column2]

  This protects against the database having multiple rows with the
  same values for both :column1 and :column2.  This is different
  from:

    validates_uniqueness_of :column1, :column2

  Which checks that the value of column1 is unique in the table, and
  that the value of column2 is unique in the table (which is much
  more restrictive).

Other Improvements
------------------

* Dataset methods insert_sql, delete_sql, and update_sql respect the
  :sql option, allowing you to do things such as:

    ds = DB['INSERT INTO t (time) VALUES (CURRENT_TIMESTAMP)']
    ds.insert
    ds.insert

* The database adapters (at least MySQL, PostgreSQL, SQLite, and
  JDBC) generally raise Sequel::DatabaseError for database problems,
  making it easier to tell what is a true database error versus an
  error raised by Sequel itself.

* Sequel uses the async features of ruby-pg so that the entire
  interpreter is not blocked while waiting for the results of
  queries.

* Sequel now supports the 2008.08.17 version of ruby-pg.

* MSSQL support has been improved when using the ODBC and ADO
  adapters.

* Index names are quoted and creating or dropping indexes.

* Automatically generated column accessor methods no longer override
  instance methods specified by plugins.

* Inserting a row with an already specified primary key inside a
  transaction now works correctly when using PostgreSQL.

* before_save and before_update hooks now work as expected when using
  save_changes.

* count and paginate now work correctly on graphed datasets.

Backwards Compatibility
-----------------------

* The SQLite adapter now raises Sequel::DatabaseError instead of
  Sequel::Error::InvalidStatement whenever an SQLite3::Exception is
  raised by the SQLite3 driver.

* Date and DateTime conversions now convert 2 digit years.  To revert
  to the previous behavior:

    Sequel.convert_two_digit_years = false

  Note that Ruby 1.8 and 1.9 handle Date parsing differently, so
  there is no backwards compatibility change for Ruby 1.9.  However,
  this also means that the MM/DD/YY date syntax commonly used in the
  United States is not always parsed correctly on Ruby 1.9, greatly
  limiting the use of 2 digit year conversion.

* You can no longer abuse the SQL function syntax for specifying
  database types.  For example, you must change:

    :type=>:varchar[255]

  to:

    :type=>:varchar, :size=>255

---

### Doc Release Notes 2.6.0 (`doc/release_notes/2.6.0.txt`)

New Features
------------

* Schema parsing was refactored, resulting in a huge speedup when
  using MySQL.  MySQL now uses the DESCRIBE statement instead of the
  INFORMATION_SCHEMA.  PostgreSQL now uses the pg_* system catalogs
  instead of the INFORMATION schema.

* The schema information now includes the :primary_key field.  Models
  now use this field to automatically determine the primary key for
  a table, so it no longer needs to be specified explicitly.  Models
  even handle the composite primary key case.

* The raise_on_typecast_failure switch was added, with it being true
  by default (so no change in behavior).  This allows the user to
  silently ignore errors when typecasting fails, at the global, class,
  and instance levels.

    Sequel::Model.raise_on_typecast_failure = false # Global
    Artist.raise_on_typecast_failure = true # Class
    artist = Artist.new
    artist.raise_on_typecast_failure = false # Instance

    Album.raise_on_typecast_failure = true
    Album.new(:numtracks=>'a') # => raises Sequel::Error::InvalidValue
    Album.raise_on_typecast_failure = false
    Album.new(:numtracks=>'a') # => #<Album @values={:numtracks=>"a"}>

* Associations' orders are now respected when eager loading via
  eager_graph.  Sequel will qualify the columns in the order with
  the alias being used, so you can have overlapping columns when
  eager loading multiple associations.

    Artist.one_to_many :albums, :order=>:name
    Album.one_to_many :tracks, :order=>:number
    Artist.order(:artists__name).eager_graph(:albums=>:tracks).sql
    # => ... ORDER BY artists.name, albums.name, tracks.number

* The support for CASE expressions has been enhanced by allowing the
  use of an optional expression:

    {1=>2}.case(0, :x)
    # => CASE x WHEN 1 THEN 2 ELSE 0 END
    [[:a, 1], [:b, 2], [:c, 3]].case(4, :y)
    # => CASE y WHEN a THEN 1 WHEN b THEN 2 WHEN c THEN 3 ELSE 4 END

  Previously, to get something equivalent to this, you had to do:

    {{:x=>1}=>2}.case(0)
    # => CASE WHEN (x = 1) THEN 2 ELSE 0 END
    [[{:y=>:a}, 1], [{:y=>:b}, 2], [{:y=>:c}, 3]].case(4)
    # => CASE WHEN (y = a) THEN 1 WHEN (y = b) THEN 2 WHEN (y = c)
         THEN 3 ELSE 4 END

* You can now change the NULL/NOT NULL value of an existing column
  using the set_column_allow_null method.

    # Set NOT NULL
    DB.alter_table(:artists){set_column_allow_null :name, false}
    # Set NULL
    DB.alter_table(:artists){set_column_allow_null :name, true}

* You can now get the schema information for a table in a non-public
  schema in PostgreSQL using the implicit :schema__table syntax.
  Before, the :schema option had to be given explicitly to
  Database#schema.  This allows models to get schema information for
  tables outside the public schema.

* Transactions are now supported on MSSQL.

* Dataset#tables now returns all tables in the database for MySQL
  databases accessed via JDBC.

* Database#drop_view can now drop multiple views at once.

Other Improvements
------------------

* The SQLite adapter now respects the Sequel.datetime_class option
  for timestamp and datetime columns.

* Adding a unique constraint no longer explicitly creates a unique
  index.  If you want a unique index, use index :unique=>true.

* If no language is specified when creating a full text index on
  PostgreSQL, the simple language is assumed.

* Errors when typecasting fails are now Sequel::Error::InvalidValue
  instead of the more generic Sequel::Error.

* Specifying constraints now works correctly for all types of
  arguments.  Previously, it did not work unless a block or
  interpolated string were used.

* Loading an association with the same name as a table in the FROM
  clause no longer causes an error.

* When eagerly loading many_to_one associations where no objects have
  an associated object, the negative lookup is now cached.

* String keys can now be used with Dataset#multi_insert, just like
  they can be used for Dataset#insert.

* Dataset#join_table now generates the correct SQL when doing the
  first join to a dataset where the first source is a dataset, when
  an unqualified column is used in the conditions.

* Cascading associations after *_to_many associations can now be
  eagerly loaded via eager_graph.

* Eagerly loading *_to_many associations that are cascaded behind a
  many_to_one association now have their duplicates removed if a
  cartesian product join is done.

* The SQLite adapter now uses string literals in all of the AS
  clauses.  While the SQL standard specifies that identifiers should
  be used, SQLite documentation explicitly states that string
  literals are expected (though it generally works with identifiers
  by converting them implicitly).

* Database methods that modify the schema now remove the cached
  schema entry.

* The hash keys that Database#schema returns when no table is
  requested are now always supposed to be symbols.

* The generation of SQL for composite foreign keys on MySQL has been
  fixed.

* A schema.rdoc file was added to the documentation explaining the
  various parts of Sequel related to schema generation and
  modification and how they interact
  (http://sequel.rubyforge.org/rdoc/files/doc/schema_rdoc.html).

* The RDoc template for the website was changed from the default
  template to the hanna template.

Backwards Compatibility
-----------------------

* The :numeric_precision and :max_chars schema entries have been
  removed.  Use the :db_type entry to determine this information,
  if available.

* The SQLite adapter used to always return Time instances for
  timestamp types, even if Sequel.datetime_class was DateTime.  For
  datetime types it always returned a DateTime instance.  It
  now returns an instance of Sequel.datetime_class in both cases.

* It's possible that the including of associations' orders when eager
  loading via eager_graph could cause problems.  You can use the
  :order_eager_graph=>false option to not use the :order option when
  eager loading via :eager_graph.

* There were small changes in SQL creation where the AS keyword is
  now used explicitly.  These should have no effect, but could break
  tests for explicit SQL.

---

### Doc Release Notes 2.7.0 (`doc/release_notes/2.7.0.txt`)

Performance Optimizations
-------------------------

* Fetching a large number of records with the PostgreSQL adapter is
  significantly faster (up to 3-4 times faster than before).

* Instantiating model objects has been made much faster, as many
  options (such as raise_on_save_failure) are now lazily loaded, and
  hook methods are now much faster if no hooks have been defined for
  that type of hook.

New Association Options
-----------------------

* The :eager_grapher option has been added allowing you to supply
  your own block to implement eager loading via eager_graph.

* many_to_one and one_to_many associations now have a :primary_key
  option, specifying the name of the column that the :key option
  references.

* many_to_many associations now have :left_primary_key and
  :right_primary_key options, specifying the columns that :left_key
  and :right_key reference, respectively.

* many_to_many associations now have a :uniq option, that adds an
  :after_load callback that makes the returned array of objects
  unique.

Other New Features
------------------

* Dataset#set_graph_aliases now allows you to supply a third argument
  for each column you want graph into the dataset, allowing you to use
  arbitrary SQL expressions that are graphed into the correct table:

    ds.set_graph_aliases!(:a=>[:b, :c], :d=>[:e, :f, 42])
    # SELECT b.c AS a, 42 AS d FROM ...
    ds.first # => {:b=>{:c=>?}, :e=>{:f=>42}}

* Dataset#add_graph_aliases was added, that adds additional graph
  aliases instead of replacing the existing ones (as
  #set_graph_aliases does).  It's basically the equivalent of
  select_more for graphs.

* Dataset#join_table changed it's final argument from a symbol
  specifying a table name to an option hash (with backwards
  compatibility kept), and adds support for a :implicit_qualifier
  option, which it uses instead of the last joined table to
  qualify columns.

* Association's :after_load callbacks are now called when eager
  loading via eager (but not when eager loading via eager_graph).

* Any expression can now be used as the argument to Symbol#like,
  which means that you can pattern match columns to other columns.
  Before, it always transformed the argument to a string.

    :a.like(:b)
    # 2.6.0: a LIKE 'b'
    # 2.7.0: a LIKE b

* Array#sql_array was added, allowing you to specify that an array
  in ruby be treated like an array in SQL.  This is true anyway,
  except for arrays of all two pairs, which are treated like hashes,
  for specifying multiple conditions with the same key:

   DB[:foo].filter([:a,:b] => [[1,2],[3,4]].sql_array)
   # => SELECT * FROM foo WHERE ((a, b) IN ((1, 2), (3, 4)))

* ComplexExpression#== and #sql? were added, allowing for easier
  testing.

* Full text searching on PostgreSQL now joins multiple columns with
  a space, to prevent joining border words, and it works when there
  is a match in one column but the other column is NULL.

Other Improvements
------------------

* Instance methods added by creating associations are added to an
  anonymous module included by the class, so they can be overridden
  in the class while still allowing the use of super to get the
  default behavior (this is similar to column accessor methods).

* Many improvements were added to support using multiple schemas in
  PostgreSQL.

* Model::Validation::Errors objects are now more compatible with
  Rails, by adding a #count method and making #on return nil if there
  are no error messages for that attribute.

* Serialized columns in models are no longer typecast.

* Associations are now inherited when a model class is subclassed.

* Many improvements were made that should make adding custom
  association types easier.

* A corner case in eager_graph where the wrong table name would be
  used to qualify a column name has been fixed.

* Dataset's cached column information is no longer modified if #each
  is called with an option that modifies the columns.

* You should now be able to connect to Oracle via the JDBC adapter,
  and with the same support it has when using the oracle adapter.

* Model.association_reflections is now a public methods, so you can
  grab a hash of all association reflections at once (keyed by
  association name symbol).

* The :encoding/:charset option now works in the PostgreSQL adapter
  if the postgres-pr driver is used.

* The numeric(x,y) type is now interpreted as decimal.

Backwards Compatibility
----------------------

* The first argument to Model#initialize must be a hash, you can no
  longer use nil.  For example, the following code will break if
  :album is not in params:

    Album.new(params[:album])

  Additionally, Model#initialize does not call the block if the
  second argument is true.

* The Sequel::Model.lazy_load_schema setting was removed.  It should
  no longer be necessary now that schema loading is relatively speedy,
  and schemas can be loaded at startup and cached.

* The PostgreSQL adapter will default to using a unix socket in /tmp
  if no host is specified.  Before, a TCP/IP socket to localhost was
  used if no host was specified.  This change makes Sequel operate
  similarly to the PostgreSQL command line tools.

* The ASSOCIATION_TYPES constant has changed from an array to a hash
  and it has been moved.  The RECIPROCAL_ASSOCIATIONS constant has
  been removed.  This is unlikely to matter unless you were using
  custom association types.

* The PostgreSQL adapter now sets the PostgreSQL DateStyle, in order
  to implement an optimization.  To turn this off, set
  Sequel::Postgres.use_iso_date_format = false.

* When using the PostgreSQL adapter, in many places the schema is
  specified explicitly.  If you do not specify a schema, a default
  one is used (public by default).  If you use a schema other than
  public for your work, use Database#default_schema= to set it.  For
  any table outside of the default schema, you should specify the
  schema explicitly, even if it is in the PostgreSQL search_path.

* Model::Validation::Errors#on now returns nil instead of [] if there
  are no errors for an attribute.

* Hooks added to a superclass after a subclass has been created no
  longer have an effect on the subclass.

* The Postgres.string_to_bool method has been removed.

* PostgreSQL full text searching now always defaults to using the
  simple dictionary.  If you want to use another dictionary, it must
  be specified explicitly, both when searching and when creating a
  full text index.

---

### Doc Release Notes 2.8.0 (`doc/release_notes/2.8.0.txt`)

New Features
------------

* Sequel now supports database stored procedures similar to its
  support for prepared statements.  The API is as follows:

    DB[:table].call_sproc(:select, :mysp, 'param1', 'param2')
    # or
    sp = DB[:table].prepare_sproc(:select, :mysp)
    sp.call('param1', 'param2')
    sp.call('param3', 'param4')

  This works with Model datasets as well, allowing them to return
  model objects:

    Album.call_sproc(:select, :new_albums)
    #=> [#<Album ...>, #<Album ...>]

  You can call a stored procedure directly on the Database object
  if you want to, but the results and API are adapter dependent,
  and you definitely shouldn't do it if the stored procedure returns
  rows:

    DB.call_sproc(:mysp, :args=>['param1', 'param2'])

  Currently, the MySQL and JDBC adapters support stored procedures.
  Other adapters may support them in a future version.

* The connection pool code can now remove connections if the
  adapter raises a Sequel::DatabaseDisconnectError indicating that
  the connection has been lost.  When a query is attempted and
  the adapter raises this error, the connection pool removes the
  connection from the pool, and reraises the error.  The Oracle and
  PostgreSQL adapters currently support this, and other adapters may
  support it in a future version.

* Whether to upcase or quote identifiers can now be set separately.
  Previously, upcasing was done when quoting except when using SQLite,
  PostgreSQL, or MySQL.  Now, you can turn upcasing off while still
  quoting.  This may be necessary if you are using a MSSQL database
  that has lower case table names that conflict with reserved words.
  It also allows you to uppercase identifiers when using SQLite,
  PostgreSQL, or MySQL, which may be beneficial in certain cases.

  To turn upcasing on or off:

    # Global
    Sequel.upcase_identifiers = true
    # Database
    DB = Sequel.connect("postgres://...", :upcase_identifiers=>true)
    DB.upcase_identifiers = false
    # Dataset
    ds = DB[:items]
    ds.upcase_identifiers = true

* Options are now supported when altering a columns type:

    DB.alter_table(:items) do
      set_column_type :score, :integer, :unsigned=>true
      set_column_type :score, :varchar, :size=>30
      set_column_type :score, :enum, :elements=>['a', 'b']
    end

* Standard conforming strings are now turned on by default in the
  PostgreSQL adapter.  This makes PostgreSQL not interpret backslash
  escapes.  This is the PostgreSQL recommended setting, which will be
  the default setting in a future version of PostgreSQL.  If you
  don't want for force the use of standard strings, use:

    Sequel::Postgres.force_standard_strings = false

  You need to do that after you call Sequel.connect but before you
  use the database for anything, since that setting is set on
  initial connection.

* Sequel now raises an error if you attempt to use EXCEPT [ALL] or
  INTERSECT [ALL] on a database that doesn't support it.

* Sequel now raises an error if you attempt to use DISTINCT ON with
  MySQL or Oracle, which don't support it.

* A subadapter for the Progress RDBMS was added to the ODBC adapter.
  To connect to a Progress database, use the :db_type=>'progress'
  option.  This adapter targets Progress 9.

* The ODBC adapter now supports transactions.

* The MSSQL shared adapter now supports multi_insert (for inserting
  multiple rows at once), and unicode string literals.

Other Improvements
------------------

* There were many improvements related to using schemas in databases.
  Using schema-qualified tables should work in most if not all cases
  now.  Model associations, getting the schema, joins, and many other
  parts of Sequel were modified to allow the use of schema-qualifed
  tables.

* You can now use literal strings with placeholders as well as
  subselects when using prepared statements.  For example, the
  following all work now:

    DB[:items].filter("id = ?", :$i).call(:select, :i=>1)
    DB[:items].filter(:id=>DB[:items].select(:id)\
      .filter(:id=>:$i)).call(:select, :i=>1)
    DB["SELECT * FROM items WHERE id = ?", :$i].call(:select, :i=>1)

* Model#initialize received a few more micro-optimizations.

* Model#refresh now clears the changed columns as well as the
  associations.

* You can now drop columns inside a transaction when using SQLite.

* You can now submit multiple SQL queries at once in the MySQL
  adapter:

    DB['SELECT 1; SELECT 2'].all
    #=> [{:"1"=>1, :"2"=>2}]

  This may fix issues if you've seen a MySQL "commands out of sync"
  message.  Note that this doesn't work if you are connecting to
  MySQL via JDBC.

* You can now use AliasedExpressions directly in table names given
  to join_table:

    DB.from(:i.as(:j)).join(:k.as(:l), :a=>:b)
    #=> ... FROM i AS j INNER JOIN k AS l ON (l.a = j.b)

* Database#rename_table once again works on PostgreSQL.  It was
  broken in 2.7.0.

* The interval type is now treated as it's own type. It was
  previously treated as an integer type.

* Subselects are now aliased correctly when using Oracle.

* UNION, INTERSECT, and EXCEPT statements now appear before ORDER
  and LIMIT on most databases.  If you use these constructs, please
  test and make sure that they work correctly with your database.

* SQL EXCEPT clause now works on Oracle, which uses MINUS instead.

* Dataset#exists now returns a LiteralString, to make it easier to
  use.

* The Sequel.odbc_mssql method was removed, as the odbc_mssql adapter
  was removed in a previous version.  Instead, use:

    Sequel.odbc(..., :db_type=>'mssql')

Backwards Compatibility
----------------------

* The hash returned by Database#schema when no table name is provided
  uses quoted strings instead of symbols as keys.  The hash has a
  default proc, so using the symbol will return the same value as
  before, but if you use each to iterate through the hash, the keys
  will be different.  This was necessary to handle schema-qualified
  tables.

* Database#table_exists? no longer checks the output of
  Database#tables.  If the table exists in the schema, it returns
  true, otherwise, it does a query.  This was necessary because
  table_exists? accepts multiple formats for table names and
  Database#tables is an array of symbols.

* When getting the schema on PostgreSQL, the default schema is now
  used even if the :schema=>nil option is used.

---

### Doc Release Notes 2.9.0 (`doc/release_notes/2.9.0.txt`)

New Features
------------

* Compound SQL statement (i.e. UNION, EXCEPT, and INTERSECT) support
  is much improved.  Chaining compound statement calls now longer
  wipes out previous compound statements calls of the same type.
  Also, the ordering of the compound statements is no longer fixed
  per adapter, it now reflects the order they were called on the
  object.  For example, the following now work as expected:

    ds1.union(ds2).union(ds3)
    ds1.except(ds2).except(ds3)
    ds1.intersect(ds2).intersect(ds3)
    ds1.union(ds2).except(ds3)
    ds1.except(ds2).intersect(ds3)
    ds1.intersect(ds2).union(ds3)

* Exception classes ValidationFailure and BeforeHookFailure were
  added so it is easier to catch a failed validation.  These are
  both subclasses of Sequel::Error, so there shouldn't be any
  backwards compatibility issues.  Error messages are also improved,
  as the ValidationFailure message is a string containing all
  validation failures and the BeforeHookFailure message contains
  which hook type caused the failure (i.e. before_save,
  before_create, or before_validation).

* The sequel command line tool now has a -L option to load
  all files in the given directory.  This is mainly useful for
  loading a directory of model files. The files are loaded
  after the database connection is set up.

* Methods to create and drop database functions, triggers, and
  procedural languages were added to the PostgreSQL adapter.

Other Improvements
------------------

* Database#schema now raises an error if you pass a table that
  doesn't exist.  Before, some adapters would return an empty schema.
  The bigger problem with this is that it made table_exists? return
  the wrong value, since it looks at the Database's schema.
  Generally, this bug would show up in the following code:

    class Blah < Sequel::Model
    end
    Blah.table_exists? # True even if blahs is not a table

* AlterTableGenerator#add_foreign_key now works for MySQL.

* Error messages in model association methods that add/remove an
  associated object are now more descriptive.

* Dataset#destroy for model datasets now works with databases that
  can't handle nested queries.  However, it now loads all model
  objects being destroyed before attempting to destroy any of them.

* Dataset#count now works correctly for compound SQL statements
  (i.e. UNION, EXCEPT, and INTERSECT).

* BigDecimal NaN and (+/-)Infinity values are now literalized
  correctly.  Database support for this is hit or miss.  Sqlite will
  work correctly, PostgreSQL raises an error if you try to store an
  infinite value in a numeric column (though it works for float
  columns), and MySQL converts all three to 0.

* The SQLite adapter no longer loses primary key information when
  dropping columns.

* The SQLite adapter now supports dropping indices.

* A bug in the MSSQL adapter's literalization of LiteralStrings has
  been fixed.

* The literalization of blobs on PostgreSQL (bytea columns) has been
  fixed.

* Sequel now raises an error if you attempt to subclass Sequel::Model
  before setting up a database connection.

* The native postgresql adapter has been changed to only log client
  messages of level WARNING by default.  You can modify this via:

    Sequel::Postgres.client_min_messages = nil # Use Server Default
    Sequel::Postgres.client_min_messages = :notice # Use NOTICE level

* Model#inspect now calls Model#inspect_values for easier
  overloading.

Backwards Compatibility
----------------------

* The API to Model#save_failure (a private method) was changed to
  remove the second argument.

* SQLite columns with type numeric, decimal, or money are now
  returned as BigDecimal values.  Before, they were probably returned
  as strings.

---

### Doc Release Notes 3.0.0 (`doc/release_notes/3.0.0.txt`)

Deprecated Methods/Features Removed
-----------------------------------

Methods and features that were deprecated in 2.12.0 have been removed
in 3.0.0.  Many features were moved into plugins or extensions, so in
many cases you just need to require an extension or use Model.plugin
and not make any changes to your code.  See the 2.12.0 release notes
for the list of methods/features deprecated in 2.12.0.

If you are upgrading from a previous 2.x release, please upgrade to
2.12.0 first, fix your code to remove all deprecation warnings, and
then upgrade to 3.0.0.

New Adapter
-----------

* Sequel now has an Amalgalite adapter.  Amalgalite is a ruby
  extension that embeds SQLite without requiring a separate SQLite
  installation.  The adapter is functionality complete but
  significantly slower than the native SQLite adapter.

New Features
------------

* The JDBC, PostgreSQL, MySQL, and SQLite adapters all now have a
  Database#indexes method that returns indexes for a given table:

    DB.indexes(:songs)
    => {:songs_name_index=>{:unique=>true, :columns=>[:name]},
        :songs_lyricid_index=>{:unique=>false, :columns=>[:lyricid]}}

* A schema_dumper extension was added to Sequel.  It supports dumping
  the schema of a table (including indexes) as a string that can be
  evaluated in the context of a Database object to create the table.
  It also supports dumping all tables in the database as a string
  containing a Migration subclass that will rebuild the database.

    require 'sequel/extensions/schema_dumper'
    DB.dump_table_schema(:table)
    DB.dump_schema_migration
    DB.dump_schema_migration(:same_db=>true)
    DB.dump_schema_migration(:indexes=>false)
    DB.dump_indexes_migration

  The :same_db option causes Sequel to not translate column types
  to generic column types.  By default, the migration created will
  use generic types so it will run on other databases.  However, if
  you only want to support a single database, using the :same_db
  option will make the migration use the exact database type parsed
  from the database.

  The :indexes=>false option causes indexes not be included in the
  migration.  The dump_indexes_migration can be used to create a
  separate migration with the indexes.  This can be useful if you 
  plan on loading a lot of data right after creating the tables,
  since it is faster to add indexes after the data has been added.

* Using options with the generic database types is now supported to
  a limited extent.  For example, the following code now works:

    DB.create_table(:table) do
      String :a, :size=>50               # varchar(50)
      String :b, :text=>true             # text
      String :c, :fixed=>true, :size=>30 # char(30)
      Time :ts                           # timestamp
      Time :t, :only_time=>true          # time
    end

* Using Dataset#filter and related methods with multiple arguments
  now works much more intuitively:

    # 2.12.0
    dataset.filter(:a, :b=>1) # a IS NULL AND (b = 1) IS NULL
    # 3.0.0
    dataset.filter(:a, :b=>1) # a AND b = 1

* You can now create temporary tables by passing the :temp=>true
  option to Database#create_table.

* The Oracle shared adapter now supports emulation of
  autoincrementing primary keys by creating a sequence and a trigger,
  similar to how the Firebird adapter works.

* The Database#database_type method was added that returns a symbol
  specifying the database type being used.  This can be different
  than Database.adapter_scheme if you are using an adapter like
  JDBC that allows connecting to multiple different types of
  databases.

* Database#drop_index and related methods now support an options
  hash that respects the :name option, so they can now be used to
  drop an index that doesn't use the default index name.

* The PostgreSQL shared adapter now supports a
  Database#reset_primary_key_sequence method to reset the
  primary key sequence for a given table, based on code from
  ActiveRecord.

* SQL::QualifiedIdentifiers can now be qualified, allowing you to do:

   :column.qualify(:table).qualify(:schema)
 
* Using the :db_type=>'mssql' option with the DBI adapter will now
  load the MSSQL support.

* The MySQL shared adapter now supports Dataset#full_text_sql, which
  you can use in queries like the following:

    ds.select(:table.*, ds.full_text_sql(:column, 'value').as(:ft))

Other Improvements
------------------

* Sequel will now release connections from the connection pool
  automatically if they are held by a dead thread.  This can happen
  if you are using MRI 1.8 and you are heavily multithreaded or
  you call Thread#exit! or similar method explicitly.  Those methods
  skip the execution of ensure blocks which normally release the
  connections when the threads exit.

* Model#save will now always use the same server when refreshing data
  after an insert.  This fixes an issue when Sequel's master/slave
  database support is used with models.

* SQL Array references are now quoted correctly, so code like this
  now works:

    :table__column.sql_subscript(1)

* The PostgreSQL shared adapter now handles sequences that need to be
  quoted correctly (previously these were quoted twice).

* String quoting on Oracle no longer doubles backslashes. 

* Database#count now works correctly when used on MSSQL when using
  an adapter that doesn't handle unnamed columns.

* Full text searching in the MySQL adapter now works correctly when
  multiple search terms are used.

* Altering a column's name, type, default, or NULL/NOT NULL status
  on MySQL now keeps other relevant column information.  For example,
  if you alter a column's type, it'll keep an existing default. This
  functionality isn't complete, there may be other column information
  that is lost.

* Fix creation of an index with a given type on MySQL, since MySQL's
  documentation lies.

* The schema parser now handles decimal types with size specifiers,
  fixing use on MySQL.

* Dataset#quote_identifier now works correctly when given an
  SQL::Identifier.  This allows you to do:

    dataset.select{sum(hours).as(hours)}

Backwards Compatibility
-----------------------

* Sequel will now use instance_eval on all virtual row blocks without
  an argument.  This can lead to much nicer code:

    dataset.filter{(number > 10) & (name > 'M')}
    # WHERE number > 10 AND name > 'M'

  2.12.0 raised a deprecation warning if you used a virtual row block
  without an argument and you hadn't set
  Sequel.virtual_row_instance_eval = true.

* Dataset#exclude now inverts the given argument, instead of negating
  it. This only changes its behavior if it is called with a hash or
  array of all two pairs that have more than one element.

    # 2.12.0
    dataset.exclude(:a=>1, :b=>1) # a != 1 AND b != 1
    # 3.0.0
    dataset.exclude(:a=>1, :b=>1) # a != 1 OR b != 1

  This was done for consistency, since exclude would only negate a
  hash if it was given an argument, it would invert the same hash
  if you used a block:

    # 2.12.0
    dataset.exclude{{:a=>1, :b=>1}} # a != 1 OR b != 1
  
  If you want the previous behavior,
  change the code to the following:

    dataset.filter({:a=>1, :b=>1}.sql_negate)

* As noted above, the methods/features deprecated in 2.12.0 were
  removed.

* The private Dataset#select_*_sql methods now only take a single
  argument, the SQL string being built.

* Dataset#from when called without arguments would previously cause an
  error to be raised when the SQL string is generated.  Now it causes
  no FROM clause to be used, similar to how Dataset#select with no
  arguments causes SELECT * to be used.

* The internals of the generic type support and the schema generators
  were changed significantly, which could have some fallout in terms
  of old migrations breaking if they used the generic types and were
  relying on some undocumented behavior (such as using Integer as a
  type with the :unsigned option).

* The Firebird adapter no longer translates the text database
  specific type.  Use the following instead:
    
    String :column, :text=>true 

* The MySQL shared adapter used to use the timestamp type for Time,
  now it uses datetime.  This is because the timestamp type cannot
  represent everything that the ruby Time class can represent.

* Metaprogramming#metaattr_accessor and #metaattr_reader methods were
  removed.

* Dataset#irregular_function_sql was removed.

---

### Doc Release Notes 3.1.0 (`doc/release_notes/3.1.0.txt`)

New Plugins
-----------

3 new plugins were added that implement features supported by
DataMapper: identity_map, tactical_eager_loading, and
lazy_attributes.  These plugins don't add any real new features, 
since you can do most of what they allow before simply by being
a little more explicit in your Sequel code. However, some people
prefer a less explicit approach that uses a bit more magic, and
now Sequel can accommodate them.

* The identity_map plugin allows you to create a 1-1
  correspondence of model objects to database rows via a temporary
  thread-local identity map.  It makes the following statement true:

    Sequel::Model.with_identity_map do
      Album.filter{(id > 0) & (id < 2)}.first.object_id == \
        Album.first(:id=>1).object_id
    end

  As the code above implies, you need to use the with_identity_map
  method with a block to use the identity mapping feature.

  By itself, identity maps don't offer much, but Sequel uses them
  as a cache when looking up objects by primary key or looking up
  many_to_one associated objects.  Basically, it can be used as a
  performance enhancer, and it also allows the support of the
  lazy_attributes plugin.

  The identity_map plugin is expected to be most useful in web
  applications.  With that in mind, here's a Rack middleware that
  wraps each request in a with_identity_map call, so the
  identity_map features are available inside the web app:

    Sequel::Model.plugin :identity_map
    class SequelIdentityMap
      def initialize(app)
        @app = app
      end
      def call(env)
        Sequel::Model.with_identity_map{@app.call(env)}
      end
    end

* The tactical_eager_loading plugin allows you to eagerly load an
  association for all models retrieved in the same group whenever
  one of the models accesses the association:

    # 2 queries total
    Album.filter{id<100}.all do |a|
      a.artists
    end

  In order for this correctly, you must use Dataset#all to load the
  records, you cannot iterate over them via Dataset#each.  This is
  because eager loading requires that you have all records in
  advance, and when using Dataset#each you cannot know about later
  records in the dataset.

  Before, you could just be explicit about the associations you
  needed and make sure to eagerly load them using eager before
  calling Dataset#all.

* The lazy_attributes plugin builds on the identity_map and
  tactical_eager_loading plugins and allows you to create
  attributes that are lazily loaded from the database:

    Album.plugin :lazy_attributes, :review

  This will remove the :review attribute from being selected by
  default.  If you try to access the attribute after it is selected,
  it'll retrieve the value from the database.  If the object was
  retrieved with a group of other objects and an identity map is in
  use, it'll retrieve the lazy attribute for the entire group of
  objects at once, similar to the tactical_eager_loading plugin:

    # 2 queries total
    Sequel::Model.with_identity_map do
      Album.filter{id<100}.all do |a|
        a.review
      end
    end

  Before, you could just set the default selected columns for a model
  to not include the lazy attributes, and just use select_more to
  add them to any query where the resulting model objects will
  need the attributes.

* A many_through_many plugin was also added.  This very powerful
  plugin allows you to create associations to multiple objects through
  multiple join tables.  Here are some examples:

    # Assume the following many to many associations:
    Artist.many_to_many :albums
    Album.many_to_many :tags

    # Same as Artist.many_to_many :albums
    Artist.many_through_many :albums,
      [[:albums_artists, :artist_id, :album_id]]

    # All tags associated to any album this artist is associated to
    Artist.many_through_many :tags,
      [[:albums_artists, :artist_id, :album_id],
       [:albums, :id, :id],
       [:albums_tags, :album_id, :tag_id]]

    # All artists associated to any album this artist is associated to
    Artist.many_through_many :artists,
      [[:albums_artists, :artist_id, :album_id],
       [:albums, :id, :id],
       [:albums_artists, :album_id, :artist_id]]

    # All albums by artists that are associated to any album this
    # artist is associated to
    Artist.many_through_many :artist_albums,
      [[:albums_artists, :artist_id, :album_id],
       [:albums, :id, :id],
       [:albums_artists, :album_id, :artist_id],
       [:artists, :id, :id],
       [:albums_artists, :artist_id, :album_id]]

  Basically, for each join table between this model and the
  associated model, you use an array with a join table name, left key
  name (key closer to this model), and right key name (key closer to
  the associated model).

  In usual Sequel fashion, this association type works not just
  for single objects, but it can also be eagerly loaded via eager or
  eager_graph.  There are numerous additional configuration options,
  please see the RDoc for details.

New bin/sequel Features
-----------------------

The bin/sequel command line tool now supports the following options:

* -C: Copies one database to another.  You must specify two database
  arguments.  Works similar to Taps, copying the table schema, then
  the table data, then creating the indexes.

* -d: Dump the schema of the database in the database-independent
  migration format.

* -D: Dump the schema of the database in the database-specific
  migration format.

* -h: Display the help

* -t: Output the full backtrace if an exception is raised

The bin/sequel tool is now better about checking which options can
be used together.  It also now supports using the -L option multiple
times and having it load model files from multiple directory trees.

New Features
------------

* Dataset#qualify_to and #qualify_to_first_source were added.  They
  allow you to qualify unqualified columns in the current dataset
  to the given table or the first source. This can be used to join
  a dataset that has unqualified columns to a new table which has
  columns with the same name.
  
  For example, take this dataset:
  
    ds = DB[:albums].select(:name).order(:name).filter(:id=>1)
    # SELECT name FROM albums WHERE (id = 1) ORDER BY name

  Let's say you want to join it to the artists table:
  
    ds2 = ds.join(:artists, :id=>:artist_id)
    # SELECT name FROM albums 
    #  INNER JOIN artists ON (artists.id = albums.artist_id)
    #  WHERE (id = 1) ORDER BY name
    
  That's going to give you an error, as the artists table already has
  columns named id and name.  This new feature allows you to do the
  following:
  
    ds2 = ds.qualify_to_first_source.join(:artists, :id=>:artist_id)
    # SELECT albums.name FROM albums
    #  INNER JOIN artists ON (artists.id = albums.artist_id)
    #  WHERE (albums.id = 1) ORDER BY albums.name
    
  By doing this, all unqualified columns are qualified, so you get
  a usable query.  This is expected to be most useful for users that
  have a default order or filter on their models and want to join
  the model to another table.  Before you had to replace the filters,
  selection, etc. manually, or use qualified columns by default even
  though the weren't needed in most cases.

* Savepoints are now supported using SQLite and MySQL, assuming you
  are using a database version that supports them.  You need to
  pass the :savepoint option to Database#transaction to use a
  savepoint.

* Model plugins can now depend on other plugins, simply by calling
  the Model.plugin method inside the plugin's apply method:

    module LazyAttributes
      def self.apply(model)
        model.plugin :tactical_eager_loading
      end

* Model.plugin now takes a block with is passed to the plugin's
  apply and configure method (see Backwards Compatibility section for
  more information on the configure method).

* You can see which plugins are loaded for a model by using
  Model.plugins.

* You can use Sequel.extension method to load extensions:

    Sequel.extension :pagination, :query

  This will only load extensions that ship with Sequel, unlike the
  Model.plugin method which will also load external plugins.

* You can now use Database#create_table? to create the table if it
  doesn't already exist (a very common need, it seems).  The schema
  plugin now supports Model.create_table? as well.

* #sql_subscript is now an allowed method on most SQL expression
  objects that Sequel generates.  Also, arguments to #sql_subscript
  can now be other expressions instead of just integers.

* Associations can now take a :cartesian_product_number option, which
  can be used to tell Sequel whether to turn on duplicate object
  detection when eagerly loading objects through eager_graph.  This
  number should be 0 if the association can never create multiple
  rows for each row in the current table, 1 if it can create multiple
  rows in the each row in the current table, and 2 if the association
  itself causes a cartesian product.

* On MySQL, Dataset#insert_ignore now affects #insert as well as
  multi_insert and import.

* Database#create_table now supports an :ignore_index_errors option,
  and Database#add_index now supports an :ignore_errors option.
  These are used by the schema_dumper when dumping an database
  schema to be restored on another database type, since indexes
  aren't usually required for proper operation and some indexes
  can't be transferred.

* The ADO adapter now takes a :provider option, which can be used
  to set the provider.

* The ADO adapter now takes a :command_timeout option, which tells
  the connection how long to wait before giving up and raising an
  exception.

* The Sequel.amalgalite adapter method was added.  Like the
  Sequel.sqlite method, you can call it with no arguments to get
  an in memory database.

Other Improvements
------------------

* MySQL "commands out of sync" errors should no longer occur unless
  you are nesting queries (calling Dataset#each inside Dataset#each).
  A bug dating at least to 2007 and possibly since the initial
  creation of the Sequel MySQL adapter was the cause.  Before, SQL
  that caused a result set that was sent using a method where Sequel
  doesn't yield a result set would cause the "commands out of sync"
  error on the following query.  For example, the following code
  would cause the error:

    DB << "SHOW DATABASES"

  If for some reason a "commands out of sync" error does occur,
  Sequel will disconnect the connection from the connection pool,
  so it won't continually stay in the pool and raise errors every
  time it is used.

* The schema_dumper extension is much better about parsing defaults
  from the database.  It can now correctly parse most defaults on
  MySQL, SQLite, and PostgreSQL databases.  It no longer includes
  defaults that it can't parse to a ruby object unless a database-
  specific dump is requested.

* The schema_dumper extension now dumps tables in alphabetical order.

* Ordered and limited datasets are now handled correctly when using
  union, intersect, and except.  Also, union, intersect, and except
  now always return a from_self dataset, so further limiting,
  filtering, and ordering of them now works as expected.

* Dataset#graph now works correctly with a complex dataset without
  having to use from_self.  Before, code like the following didn't
  do what was expected:

    DB[:albums].
      graph(DB[:artists].filter{name > 'M'}, :id=>:artist_id)

  Before, the filter on DB[:artists] would be dropped.  Now, Sequel
  correctly uses a subselect.

* You can now specify serialization formats per column in the
  serialization plugin, either by calling the plugin multiple
  times or by using the new serialize_attributes method:

    Album.plugin :serialization
    Album.serialize_attributes :marshal, :review
    Album.serialize_attributes :yaml, :name
    Album.serialization_map #{:name=>:yaml, :review=>:marshal}

  The public API for the serialization plugin is still backwards
  compatible, but the internals have changed slightly to support
  this new feature.

* You can now use eager_graph to eagerly load associations for models
  that lack primary keys.

* The :eager_graph association option now works when lazily-loading
  many_to_many associations.

* Dataset#add_graph_aliases now works correctly even if
  set_graph_aliases hasn't been used.

* The PostgreSQL Database#tables method now assumes the public schema
  if a schema is not given and there is no default_schema.

* The PostgreSQL Database#indexes method no longer returns partial
  indexes or functional indexes.
  
* The MySQL Database#indexes method no longer returns indexes on
  partial columns (prefix indexes).

* Default values for String :text=>true and File columns on MySQL
  are ignored, since MySQL doesn't support them.  They are not
  ignored if you use text and blob, since then you are using the
  database-specific syntax and Sequel doesn't do translation when
  the database-specific syntax is used.

* On PostgreSQL, attempting the reset the primary key sequence for a
  table without a primary key no longer causes an error.

* Using a placeholder string in an association's :condition option
  now works correctly (e.g. :conditions=>['n = ?', 1])

* An error is no longer raised if you attempt to load a plugin that
  has a DatasetMethods module but no public dataset methods.

* The check for dataset[n] where n is an integer was fixed.  It now
  raises an error inside of returning a limited dataset.

* On PostgreSQL, Dataset#insert with static SQL now works correctly.

* A reflection.rdoc file was added giving an overview of Sequel's
  reflection support.

* The Migrator now works correctly with file names like
  001_12312412_file_name.rb.

* The association code now requires the classes match when looking
  for a reciprocal association.

* An unlikely threading bug (race condition) was possible when using
  the validation_class_methods plugin. The plugin was refactored and
  now uses a mutex to avoid the issue.  One of the refactoring changes
  makes it so that you can no longer use a class level validation
  inside a Class.new block (since inherited isn't called until the
  block finishes).

* The exception messages when Sequel.string_to_* fail have been fixed.

* The String :text=>true generic database type has been fixed when
  using the Firebird adapter.

Backwards Compatibility
-----------------------

* A plugin's apply method is now only called the first time a plugin
  is loaded.  Plugins can now have a configure method that is called
  every time the plugin is loaded, and is always called after the
  instance methods, class methods, and dataset method submodules have
  been added to the model.  This is different from apply, which is
  called before the submodules are loaded.

  If you are a plugin author, please check your implementation to
  make sure this doesn't cause problems for you.  If you have
  questions, please post on the Sequel mailing list.

  This new plugin feature will make certain things a lot easier, and
  it should be mostly backwards compatible.  However, if a plugin
  was previously expected to be loaded multiple times with the apply
  method called each time, it will no longer work correctly.

* The plugin_opts methods defined now include multiple args in an
  array if multiple args are given.  Before, the plugin_opts methods
  just returned the first argument.

* Database#table_exists? no longer checks the cached schema
  information.  By default, it will always do a database query
  (unless overridden in an adapter).  This shouldn't affect the
  results, but if were using the method a lot and expecting it to
  use cached information, it doesn't have the same performance
  characteristics.

* The internal storage of the :select option for datasets have
  changed.  You can no longer use a hash as a way of aliasing
  columns.  Dataset#select now does the translation from the hash to
  SQL::AliasedExpression instances.  Basically, if you were using
  Dataset#clone directly with a :select option with hashes for
  aliasing, you should switch to using Dataset#select or changing
  the hashes to AliasedExpressions yourself.

---

### Doc Release Notes 3.10.0 (`doc/release_notes/3.10.0.txt`)

New Features
------------

* A real one_to_one association was added to Sequel, replacing the
  previous :one_to_one option of the one_to_many association.
  
  This is a fully backwards incompatible change, any code that uses
  the :one_to_one option of one_to_many will be broken in Sequel
  3.10.0, as that option now raises an exception.  Keeping backwards
  compatibility was not possible, as even the name of the association
  needs to be changed.  Here are the code changes you need to make:
  
  * The association definition needs to change from one_to_many to
    one_to_one, with no :one_to_one option, and with the association
    name changed from the plural form to the singular form:
    
      # Before
      Lyric.one_to_many :songs, :one_to_one=>true
      # After
      Lyric.one_to_one :song
      
  * All usage of the association when eager loading or when getting
    reflections need to use the new singular association name:
    
      # Before
      Lyric.eager(:songs).all
      Lyric.eager_graph(:songs).all
      Lyric.association_reflection(:songs)
      # After
      Lyric.eager(:song).all
      Lyric.eager_graph(:song).all
      Lyric.association_reflection(:song)
      
  Any Sequel plugins or extensions that deal with the internals of
  associations need to be made aware of the one_to_one association,
  and how it is different than one_to_many's previous :one_to_one
  option.  Here are some internal changes that may affect you:
  
  * one_to_one associations are now cached like many_to_one
    associations instead of like one_to_many associations.  So the
    cache includes the associated object or nil, instead of an array.
    Note that this change means that all custom :eager_loader options
    for one_to_one associations need to change to use this new
    caching scheme.
    
  * The one_to_one association setter method is now handled similarly
    to the many_to_one setter method, instead of using the internal
    one_to_many association add method.
    
  * Instead of raising an error when multiple rows are returned,
    one_to_one associations now use limit(1) to only return a single
    row.
    
  There were some other fixes made during these changes:
  
  * The one_to_one setter now accepts nil to disassociate the record.
    Previously, this raised an error.
    
  * If the one_to_one association already had a separate object
    associated, and you assigned a different object in the setter
    method, Sequel now disassociates the old object before
    associating the new object, fixing some potential issues if there
    is a UNIQUE constraint on the foreign key column.
    
  * Using the many_to_one association setter where the reciprocal
    association is a one_to_one association with a currently
    different cached associated object no longer raises an exception.
  
  * The nested_attributes and association_dependencies plugins
    both now correctly handle one_to_one associations.

  If you need any help migrating, please post on the Sequel Google
  Group or ask in the #sequel IRC channel.

* Both many_to_one and one_to_one associations now use before_set
  and after_set callbacks instead of trying to make the one_to_many
  and many_to_many associations' (before|after)_(add|remove)
  callbacks work.
  
  This change makes the code simpler, makes writing callbacks easier,
  and no longer requires Sequel to send a query to the database to
  get the currently associated object in the many_to_one association
  setter method (you can still do so manually in a before_set
  callback if you want to).
  
* Dataset#for_update was added as a default dataset method.
  Previously, it was only supported on PostgreSQL.  It has been
  tested to work on PostgreSQL, MySQL, SQLite (where it is ignored),
  H2, and MSSQL.
  
* Dataset#lock_style was added as a backbone for Dataset#for_update,
  but allowing you to specify custom lock styles.  These can either
  be symbols recognized by the adapters, or strings which are treated
  as literal SQL.

* Model#lock! was added, which uses Dataset#for_update to lock model
  rows for specific instances.  Combined with the Dataset#for_update,
  Sequel now has an equivalent to ActiveRecord's pessimistic locking
  support.

* A composition plugin was added, given similar functionality as
  ActiveRecord's composed_of.
  
  The composition plugin allows you to easily define getter and
  setter instance methods for a class where the backing data is
  composed of other getters and decomposed to other setters.

  A simple example of this is when you have a database table with
  separate columns for year, month, and day, but where you want to
  deal with Date objects in your ruby code.  This can be handled
  with:

    Model.composition :date, :mapping=>[:year, :month, :day]

  The :mapping option is optional, but if not used, you need define
  custom composition and decomposition procs via the :composer and
  :decomposer options.

  Note that when using the composition object, you should not modify
  the underlying columns if you are also instantiating the
  composition, as otherwise the composition object values will
  override any underlying columns when the object is saved.

* An rcte_tree plugin was added, which uses recursive common table
  expressions to load all ancestors and descendants in a single
  query.  If your database supports recursive common table
  expressions (PostgreSQL 8.4+, MSSQL 2005+, newer versions of
  Firebird), using recursive common table expressions to load
  all ancestors and descendants is significantly faster than storing
  trees as nested sets and using nested set queries.  Usage:
  
    Model.plugin :rcte_tree
   
    # Lazy loading
    model = Model.first
    model.parent
    model.children
    model.ancestors # Populates :parent association as well
    model.descendants # Populates :children association as well
   
    # Eager loading - also populates the :parent and children 
    # associations for all ancestors and descendants
    Model.filter(:id=>[1, 2]).eager(:ancestors, :descendants).all
   
    # Eager loading children and grandchildren
    Model.filter(:id=>[1, 2]).eager(:descendants=>2).all
    # Eager loading children, grandchildren, and great grandchildren
    Model.filter(:id=>[1, 2]).eager(:descendants=>3).all

* Dataset#first_source_table was added, giving you the unaliased
  version of the table for the first source.

* Add Sequel::BasicObject.remove_methods!, useful on ruby 1.8 if you
  require other libraries after Sequel that add methods to Object.
  For example, if YAML is required after sequel, then the following
  will raise an error:
  
    DB[:a].filter{x > y}
    
  because YAML adds the y method to all objects.  Now, you can call
  Sequel::BasicObject.remove_methods!, which will remove those
  methods from Sequel::BasicObject, allowing them to be used as
  intended in the above DSL.

* Sequel associations now accept an :eager_loader_key option, which
  can be useful for associations to specify the column to use for the
  key_hash for custom :eager_loaders.

* A JDBC subadapter for the AS400 database was added.

Other Improvements
------------------

* The one_to_one setter method and the one_to_many and many_to_many
  remove_all methods now apply the association options (such as
  filters) on the appropriate dataset:
  
    Artist.one_to_many :good_albums, :class=>:Album,
     :conditions=>{:good=>true}
    a = Artist[10]
    a.remove_all_good_albums
    # Before: WHERE artist_id = 10
    # After:  WHERE artist_id = 10 AND good IS TRUE

* Plugin loading now works correctly when the plugin module name
  is the same name as an already defined top level constant.  This
  means that the active_model plugin should now work correctly if
  you require active_model before loading the Sequel plugin.

* The nested_attributes plugin now preserves nested attributes for
  *_to_one associations on validation failures.

* Transactions now work correctly on Oracle when using the JDBC
  adapter.
  
* Dataset#limit once again works correctly on MSSQL 2000.  It was
  broken in Sequel 3.9.0.

* many_to_one associations now use limit(1) to ensure only one
  record is returned.  If you don't want this (because maybe you
  are using the :eager_graph association option), you need to
  set the :key option to nil and use a custom :dataset option.
  
* many_to_one and one_to_many associations now work correctly
  with the association :eager option to eagerly load associations
  specified by :eager when lazy loading the association.

* The typecast_on_load plugin now correctly handles
  reloading/refreshing the object, both explicitly and implicitly
  on object creation.

* The schema parser and dumper now return tinyint columns as
  booleans when connecting to mysql using the do adapter, since
  DataObjects now returns the columns as booleans.
  
* The schema dumper now deals better with unusual or database
  specific primary key types when using the :same_db option.

* On ruby 1.8, Sequel::BasicObject now undefs private methods in
  addition to public and protected methods.  So the following
  code now works as expected:
  
    DB[:a].filter{x > p} # WHERE x > p
    
* Sequel.connect with a block now returns the value of the block:

    max_price = Sequel.connect('sqlite://items.db') do |db|
      db[:items].max(:price)
    end
    
* MSSQL emulated offset support now works correctly when Sequel's
  core extensions are not loaded.
  
* Sequel::BasicObject now works correctly on rubinius, and almost
  all Sequel specs now pass on rubinius.
  
* The nested_attributes plugin now uses a better exception message
  no matching associated object is found.
  
* Sequel now raises a more informative error if you attempt to use
  the native sqlite adapter with the sqlite3 gem instead of the
  sqlite3-ruby gem.
  
* Multiple complex expressions with the same operator are now
  combined for simpler SQL:
  
    DB[:a].filter(:a=>1, :b=>2).filter(:c=>3)
    # Before: (((a = 1) AND (b = 2)) AND (c = 3))
    # After:  ((a = 1) AND (b = 2) AND (c = 3))
  
* The Sequel::Model dataset methods (class methods proxied to the
  model's dataset) and the Sequel::Dataset mutation methods
  (methods that have a ! counterpart to modify the object in place)
  have both been updated to use new dataset methods added in recent
  versions.

Backwards Compatibility
-----------------------

* The :one_to_one option of the one_to_many associations now raises
  an exception.  Please see the section above about the new real
  one_to_one association.

* The change to apply the association options to the one_to_many and
  many_to_many remove_all methods has the potential to break some
  code that uses the remove_all method on associations that use
  association options. This is especially true for many_to_many
  associations, as filters in many_to_many associations will often
  reference columns in the associated table, while the dataset
  used in the remove_all method only contains the join table.  Such
  cases should be handled by manually overriding the _remove_all
  association instance method in the class.  It was determined that
  it was better to issue possibly invalid queries than to issue
  queries that make unexpected modifications.

* Dataset#group_and_count now longer orders the dataset by the count.
  Since it returns a modified dataset, if you want to order the
  dataset, just call order on the returned dataset.

* many_to_one associations now require a working :class option.
  Previously, if you provided a custom :dataset option, a working
  :class option was not required in some cases.

* The MSSQL shared adapter dataset methods switched from using
  the :table_options internal option key to using the :lock internal
  option key.

---

### Doc Release Notes 3.11.0 (`doc/release_notes/3.11.0.txt`)

= New Features

* A few new features were added to query logging.  Sequel now
  includes execution time when logging queries.  Queries that
  raise exceptions are now logged at ERROR level.  You can now
  set the log_warn_duration attribute on the Database instance
  and queries that take longer than that will be logged at WARN 
  level.  By using different log levels, you can now only log
  queries that raise errors, or only log queries that take a long
  time.

    # The default - Log all successful queries at INFO level
    DB.log_warn_duration = nil

    # Log all successful queries at WARN level
    DB.log_warn_duration = 0

    # Log successful queries that take the database more than half a
    # second at WARN level, other successful queries at INFO level
    DB.log_warn_duration = 0.5

  All adapters included with Sequel have been modified to support
  the new logging API.  The previous API is still available, so
  any external adapters should still work, though switching to the
  new logging API is encouraged.
  
* Sequel::Model now has a require_modification flag.  If not set
  explicitly, it is enabled by default if the dataset provides an
  accurate number of rows matched by an update or delete statement.  
  When this setting is enabled, Sequel will raise an exception if
  you attempt to update or delete a model object and it doesn't end
  up affecting exactly one row.  For example:

    DB.create_table(:as){primary_key :id}
    class A < Sequel::Model; end
    a = A.create

    # delete object from database
    a.delete

    a.require_modification = false
    a.save # no error!
    a.delete # no error!

    a.require_modification = true
    a.save # Sequel::NoExistingObject exception raised
    a.delete # Sequel::NoExistingObject exception raised

  Like many other Sequel::Model settings, this can be set on a
  global, per class, and per instance level:

    Sequel::Model.require_modification = false # global
    Album.require_modification = true # class
    album.require_modification = false # instance

* An instance_filters plugin was added to the list of built in
  plugins, allowing you to add arbitrary filters when updating or
  destroying an instance.  This allows you to continue using models
  when previously you would have had to drop down to using datasets
  to get the desired behavior:

    class Item < Sequel::Model
      plugin :instance_filters
    end
    
    # These are two separate objects that represent the same
    # database row. 
    i1 = Item.first(:id=>1, :delete_allowed=>false)
    i2 = Item.first(:id=>1, :delete_allowed=>false)
    
    # Add an instance filter to the object. This filter is in effect
    # until the object is successfully updated or deleted.
    i1.instance_filter(:delete_allowed=>true)
    
    # Attempting to delete the object where the filter doesn't
    # match any rows raises an error.
    i1.delete # raises Sequel::Error
    
    # The other object that represents the same row has no
    # instance filters, and can be updated normally.
    i2.update(:delete_allowed=>true)
    
    # Even though the filter is now still in effect, since the
    # database row has been updated to allow deleting,
    # delete now works.
    i1.delete

* An :after_connect database option is now supported.  If provided,
  the option value should be a proc that takes a single argument.
  It will be called with the underlying connection object before
  connection object is added to the connection pool, allowing you
  to set per connection options in a thread-safe manner.

  This is useful for customizations you want set on every connection
  that Sequel doesn't already support.  For example, on PostgreSQL
  if you wanted to set the schema search_path on every connection:
                  
    DB = Sequel.postgres('dbname', :after_connect=>(proc do |conn|
      conn.execute('SET search_path TO schema1,schema2')
    end))

* A :test database option is now supported.  If set to true, it
  automatically calls test_connection to make sure a connection can
  be made before returning a Database instance.  For backwards
  compatibility reasons, this is not set to true by default, but it
  is possible that the default will change in a future version of
  Sequel.

* The Dataset#select_append method was added, which always appends
  to the existing selected columns.  It operates identically to
  select_more, except in the case that no columns are currently
  selected:

    ds = DB[:a]
    # SELECT * FROM items
    ds.select_more({:id=>DB[:b].select(:a_id)}.as(:in_b))
    # SELECT id IN (SELECT a_id FROM b) AS in_b FROM a
    ds.select_append({:id=>DB[:b].select(:a_id)}.as(:in_b))
    # SELECT *, id IN (SELECT a_id FROM b) AS in_b FROM a

* The Dataset#provides_accurate_rows_matched? method was added which
  allows you to see if the dataset will return the actual number of
  rows matched/affected by an update or delete call.

* Sequel will now emulate DISTINCT ON support using GROUP BY on
  MySQL.  On MySQL, GROUP BY is similar to DISTINCT ON, except that
  the order of returned rows is not deterministic.

* Support for connecting to Microsoft SQL Server using the JTDS JDBC
  driver was added to the jdbc adapter.

* JDNI connection strings are now supported in the JDBC adapter.

* The JDBC adapter should now work in situations where driver
  auto-loading has problems, just as when using Tomcat or Trinidad.

* Sequel's JDBC adapter schema parsing now supports a :scale option,
  useful for numeric/decimal columns.

* Sequel's schema parsing on Microsoft SQL Server now supports
  :column_size and :scale options.

* When connecting to SQLite, a Database#sqlite_version method is
  available that gives you the SQLite version as an integer (e.g.
  30613 for 3.6.13).

= Other Improvements

* Sequel no longer raises an error if you give Dataset#filter or
  related method an empty argument such as {}, [], or ''. This allows
  code such as the following to work:

    h = {}
    h[:name] = name if name
    h[:number] = number if number
    ds = ds.filter(h)
    
  Before, this would raise an error if both name and number were
  nil. 

* Numeric and decimal columns with a 0 scale are now treated as
  integer columns by the model typecasting code, since such columns
  cannot store non-integer values.

* Calling Database#disconnect when using the single threaded
  connection pool no longer raises an error if there is no current
  connection.

* When using the :ignore_index_errors options to
  Database#create_table, correctly swallow errors raised by Sequel
  due to the adapter not supporting the given index type.
  
* The JDBC adapter no longer leaks ResultSets when retrieving
  metadata.

* You can now connect to PostgreSQL when using ruby 1.9 with the
  -Ku switch.

* When using the native MySQL adapter, only tinyint(1) columns are
  now returned as booleans when using the convert_tinyint_to_bool
  setting (the default).  Previously, all tinyint columns would
  be converted to booleans if the setting was enabled.

* Correctly handle inserts returning the autogenerated keys when
  using MySQL JDBC Driver version 5.1.12 with the jdbc adapter.

* The native MySQL adapter now supports :config_default_group and
  :config_local_infile options.

* When connecting to SQLite, you can provide the :auto_vacuum,
  :foreign_keys, :synchronous, and :temp_store options for
  making the appropriate PRAGMA setting on the database in a
  thread-safe manner.  The previous thread-unsafe PRAGMA setting
  methods are available, but their use is discouraged.

* Sequel will not enable savepoints when connecting to SQLite
  unless the version is 3.6.8 or greater.

* Using limit with distinct now works correctly on Microsoft SQL
  Server.
  
* Database#rename_table now works correctly on Microsoft SQL Server.

* If you specify an explicit :provider when using the ADO adapter,
  transactions will now work correctly.  The default :provider uses
  a new native connection for each query, so it cannot work with
  transactions, or things like temporary tables.

* If you specify an explicit :provider when connecting to Microsoft
  SQL Server using the ADO adapter (e.g. SQLNCLI10 or SQLNCLI),
  Sequel is now able to provide an accurate number of rows modified
  and deleted.

* Using set_column_allow_null with a decimal column with a precision
  and scale now works correctly when connecting to Microsoft SQL
  Server.

* You can now connect to Microsoft SQL Server using the dbi adapter.

* Sequel now recognizes the NUMBER database type as a synonym for
  NUMERIC and DECIMAL, which may help some Oracle users.

* Transactions can now be rolled back correctly when connecting to
  Oracle via JDBC.

* The active_model plugin now supports ActiveModel 3.0.0beta2.

* Many documentation improvements were made, including the addition
  of a dataset basics guide, an association basics guide, an expanded
  virtual row guide, and the separation of the Sequel::Dataset RDoc
  page into sections.  Additional, the RDoc class/method
  documentation now contains links to the appropriate guides.

= Backwards Compatibility

* When connecting to SQLite, Sequel now automatically sets the
  foreign_keys PRAGMA to true, which will make SQLite 3.6.19+ use
  database enforced foreign key constraints.  If you do not want
  the database to enforce the foreign key constraints, you should
  use the :foreign_keys=>false option when connecting to the
  database.

* Sequel no longer creates #{plugin_name}_opts class, instance, and
  dataset methods for each plugin loaded.  No built-in plugin used
  them, and I couldn't find an external plugin that did either.

* The Model#associations method is no longer available if the 
  default Associations plugin is not loaded due to the 
  SEQUEL_NO_ASSOCIATIONS constant or environment variable being set.

* DISTINCT ON support is turned off by default, and only enabled when
  using PostgreSQL, since that appears to be the only database that
  supports it.  Previously, it was enabled by default and most common
  adapters turned it off.

---

### Doc Release Notes 3.12.0 (`doc/release_notes/3.12.0.txt`)

= Migration Changes

* A TimestampMigrator has been added to Sequel, and is
  automatically used if any migration has a version greater than
  20000100.  This migrator operates similarly to the default
  ActiveRecord migrator, in that it allows missing migrations.
  It differs from the ActiveRecord migrator in that it supports
  migrations with the same timestamp/version as well as a wide
  variety of timestamp formats (though the ActiveRecord default
  of YYYYMMDDHHMMSS is recommended and should be used in
  portable code).
  
  Sequel still defaults to the old migrator, but you can use the
  new one without making changes to your old migrations.  Just
  make sure your new migration starts with a version greater than
  20000100, and Sequel will automatically convert the previous
  schema table to the new format.

* A new migration DSL was added:

    Sequel.migration do
      up do
      end

      down do
      end
    end

  The old style of using a Sequel::Migration subclass is still
  supported, but it is recommended that new code use the new DSL.

* The default migrator also had significant issues fixed.  First,
  it now saves the migration version after each migration, instead
  of after all migrations, which means Sequel won't attempt to
  apply already applied migrations if there was previously an error
  when applying multiple migrations at once on a database that
  didn't support transactional schema modification.

  Second, duplicate migration versions in the default migrator now
  raise an exception, as do missing migration versions.  Neither
  should happen when using the default migrator, which requires
  consecutive integer versions, similar to the old ActiveRecord
  migrator.

* Execution times for migrations are now logged to the database's
  loggers.

= New Plugins

* A sharding plugin has been added that allows model objects to
  work well with sharded databases.  When using it, model objects
  know which shard they were retrieved from, so when you save
  the object, it is saved back to that shard.  The sharding plugin
  also works with associations, so associated records are retrieved
  from the same shard the main object was retrieved from.  The
  sharding plugin also works with both methods of eager loading, and
  provides methods that you can use to create objects on specific
  shards.

* An update_primary_key plugin has been added that allows Sequel
  to work correctly if you modify the primary key of a model object.
  This should not be necessary if you are using surrogate keys, but
  if your database uses natural primary keys which can change, this
  should be helpful.

* An association_pks plugin has been added that adds association_pks
  and association_pks= methods to model objects for both one_to_many
  and many_to_many associations.  The association_pks method returns
  an array of primary key values for the associated objects, and
  the association_pks= method modifies the database to ensure that
  the object is only associated to the objects specified by the
  array of primary keys provided to it.

* A string_stripper plugin has been added that strips all strings
  that are assigned to attribute values.  This is useful for web
  applications where you want to easily remove leading and trailing
  whitespace in form entries before storing them in the database.

* A skip_create_refresh plugin has been added that skips the refresh
  of after you save a new model object.  On most databases, Sequel
  refreshes the model object after inserting it in order to get
  values for all of the columns.  For performance reasons, you can
  use this plugin to skip the refresh if it isn't necessary for you.

= Other New Features

* Sequel::Model#set_fields and update_fields were added.  These
  methods have a similar API to set_only and update_only, but they
  operate differently. While set_only and update_only operate over
  the hash, these methods operate over the array of fields,
  so they don't raise errors if the hash contains fields not
  in the array:

    params = {:a=>1, :b=>2, :c=>3}
    album = Album[1]

    # raises Error because :a is not in the fields
    album.set_only(params, [:b, :c])

    # Just sets the value of album.b and album.c
    album.set_fields(params, [:b, :c])

  Other than handling entries in the hash that aren't in the array,
  set_fields and update_fields also handle entries not in the hash
  differently:

    # Doesn't modify the object, since the hash is empty
    album.set_only({}, [:b, :c])

    # Sets album.b and album.c to nil, since they aren't in the hash
    album.set_fields({}, [:b, :c])

* The :eager_loader association option has a new API, though the
  previous API still works.  Instead of accepting three arguments,
  it can now accept a single hash argument, which will use the
  :key_hash, :rows, and :association keys for the previous three
  arguments.  The hash will also contain a :self key whose value
  is the dataset doing the eager load, which was not possible to
  determine using the old API.

* Sequel::SQL::Expression#hash has been added so that the objects
  are now safe to use as hash keys.

* A Dataset#order_prepend method has been added allowing you to
  prepend to an existing order.  This is useful if want to modify
  a dataset's order such that it first orders by the columns you
  provide, but for any rows where the columns you provide are
  equal, uses the existing order to further order the dataset:

    ds.order(:albums__name).order_prepend(:artists__name)
    # ORDER BY artists.name, albums.name

* When creating foreign key columns, you can now use a :deferrable
  option to set up a foreign key constraint that is not checked
  until the end of the transaction:

    DB.create_table(:albums) do
      primary_key :id
      String :name
      foreign_key :artist_id, :artists, :deferrable=>true
    end

* many_to_many associations now support a :join_table_block option
  that is used by the add/remove/remove_all methods.  It can modify
  the dataset to ensure that certain columns are included when
  inserting or to add a filter so that only certain records are
  deleted.  It's useful if you have a many_to_many association that
  is filtered to only a subset of the matching rows in the join
  table.

* The single_table_inheritance plugin now supports :model_map and
  :key_map options to set up a custom mapping of column values to
  model classes.  For simple situations such as when you are mapping
  integer values to certain classes, a :model_map hash is sufficient:

    Employee.plugin :single_table_inheritance, :type_id,
     :model_map=>{1=>:Staff, 2=>:Manager}
   
  Here the :model_map keys are type_id column values, and the
  :model_map values are symbols or strings specifying class names.

  For more complex conditions, you can use a pair of procs:

    Employee.plugin :single_table_inheritance, :type_name,
     :model_map=>proc{|v| v.reverse},
     :key_map=>proc{|klass| klass.name.reverse}

  Here the type_name column is a string column holding the reverse
  of the class's name.

* The single_table_inheritance plugin now correctly sets up subclass
  filters for middle tables in a class hierarchy with more than 2
  levels.  For example, with this code:

    class Employee < Sequel::Model; end
    Employee.plugin :single_table_inheritance, :kind
    class Manager < Employee; end
    class Executive < Manager; end

  Sequel previously would not return Executives if you used
  Manager.all.  It now correctly recognizes subclasses so that it
  will return both Managers and Executives.

* Sequel::Model.qualified_primary_key_hash has been added, giving
  you a hash that can be used for filtering.  It is similar to
  primary_key_hash, but it qualifies the keys with the model's
  table.  It's useful if you have joined the table to another table
  that has columns with the same name, but you want to only look
  for a single model object in that dataset.

* For consistency, you can now use Dataset#order_append as an alias
  for order_more.

= Other Improvements

* Sequel now correctly removes schema entries when altering tables.
  Previously, some adapters that had to query the existing schema
  when altering tables resulted in the previous schema being cached.

* Sequel::Model::Errors#on now always returns nil if there are no
  errors on the attribute.  Previously, it would return an empty
  array in certain cases.  Additionally, Sequel::Model::Errors#empty?
  now returns true if there are no errors, where it certain cases
  it would return false even if there were no errors.

* The schema_dumper extension now works with tables specified as
  Sequel::SQL::Identifiers.

* Sequel now recognizes the timestamp(N) with(out) time zone column
  type.

* The lazy_attributes plugin no longer requires the core extensions
  to work correctly.

* DatabaseDisconnectError support has been added to the ODBC adapter,
  allowing Sequel to detect disconnects and remove the connection
  from the connection pool.

* A leak of JDBC statement objects when using transactions was
  fixed in the jdbc adapter.

* The jdbc adapter now gives a nicer error message if you use a
  connection string that it doesn't recognize and there is an error
  when connecting.

* Temporary table creation was fixed on Microsoft SQL Server, but
  it is not recommended as it changes the name of the table.  If
  you use Microsoft SQL Server, you should prefix your temporary
  table names with # and use the regular create table method.

* A large number of guides were added to Sequel to make it easier
  for new and existing users to learn more about Sequel.  The
  following guides were added:

  * Querying in Sequel
  * Migration and Schema Modification
  * Model Hooks
  * Model Validations
  * Sequel for SQL Users
  * Sequel for ActiveRecord Users

* RDoc section support was added to Sequel::Database, making the
  method documentation easier to read.

= Backwards Compatibility

* Sequel::Database now defines the indexes and tables methods, even
  if the adapter does not implement them, similar to how connect
  and execute are defined.  Previously, you could use respond_to? to
  check if the adapter supported them, now they raise
  Sequel::NotImplemented if the database adapter does not implement
  them.

* Sequel used to raise NotImplementedError in certain default
  definitions of methods inside Sequel::Database and Sequel::Dataset,
  when the methods were supposed to be overridden in subclasses.
  Sequel now uses a Sequel::NotImplemented exception class for these
  exceptions, which is a subclass of Sequel::Error.

* Sequel no longer applies all association options to the dataset
  used to remove all many_to_many associated objects.  You should
  use the new :join_table_block option to get similar behavior if
  you were filtering the many_to_many association based on columns
  in the join table and you wanted remove_all to only remove the
  related columns.

* Sequel now calls certain before and after hook actions in plugins
  in a different order than before.  This should not have an effect
  unless you were relying on them being called in the previous order.
  Now, when overriding before hooks in plugins, Sequel always does
  actions before calling super, and when overriding after hooks in
  plugins, Sequel always does actions after calling super.

* The hook_class_methods plugin no longer skips later after hooks if
  a previous after hook returns false.  That behavior now only occurs
  for before hooks.

* Sequel now only removes primary key values when updating objects if
  you are saving the entire object and you have not modified the
  values of the primary keys.  Previously, Sequel would remove
  primary key values when updating even if you specified the primary
  key column specifically or the primary key column was modified and
  you used save_changes/update.

* Sequel now uses explicit methods instead of aliases for certain
  methods.  This should only affect you if for example you overrode
  Dataset#group to do one thing and wanted Dataset#group_by to do
  the default action.  Now, Dataset#group_by, and methods like it, are
  explicit methods that just call the methods they previously
  aliased.  This also means that if you were overriding Dataset#group
  and explicitly aliasing group_by to it, you no longer need the
  alias.

* The single_table_inheritance plugin now uses IN instead of = for
  subclass filters.  This could lead to poor performance if the
  database has a very bad query planner.

* The private transaction_statement_object method was removed from
  the JDBC adapter, and Sequel will no longer check for the presence
  of the method in the transaction code.

* The Sequel::Migrator object is now a class instead of a module, and
  has been pretty much rewritten.  If you were using any methods of
  it besides apply and run, they no longer work.

---

### Doc Release Notes 3.13.0 (`doc/release_notes/3.13.0.txt`)

= New Plugins

* A json_serializer plugin was added that allows you to serialize
  model instances or datasets to JSON using to_json.  It requires
  the json library.  The API was modeled on ActiveRecord's JSON
  serialization support.  You can use :only and :except options
  to specify the columns included, :include to specify associations
  to include, as well pass options to nested associations using a
  hash.  In addition to serializing to JSON, it also adds support
  for parsing JSON to model objects via JSON.parse or #from_json.
  
* An xml_serializer plugin was added that allows you to serialize
  model instances or datasets to XML.  It requires the nokogiri
  library.  It has a similar API to the json_serializer plugin, using
  to_xml instead of to_json, and the from_xml class method instead
  of JSON.parse.

* A tree plugin was added that allows you to treat Sequel::Model
  objects as being part of a tree.  It provides similar features to
  rcte_tree, but works on databases that don't support recursive
  common table expressions.  In addition to the standard parent
  and children associations, it provides instance methods to get
  the ancestors, descendants, and siblings of the given tree node,
  and class methods to get the roots of the tree.

* A list plugin was added that allows you to treat Sequel::Model
  objects as being part of a list.  This adds instance methods to
  get the next and prev items in the list, or to move the item
  to a specific place in the list.  You can specify that all rows
  in the table belong to the same list, or specify arbitrary scopes
  so that the same table can contain many separate lists.

= Other New Features

* Sequel is now compatible with Ruby 1.9.2pre3.

* Sequel now supports prepared transactions/two-phase commit on
  PostgreSQL, MySQL, and H2.  You can specify that you want to
  use prepared transactions using the :prepare option which
  should be some transaction id string:
  
    DB.transaction(:prepare=>'some string') do ... end
    
  Assuming that no exceptions are raised in the transaction block,
  Sequel will prepare the transaction.  You can then commit the
  transaction later:
  
    DB.commit_prepared_transaction('some string')
    
  If you need to rollback the prepared transaction, you can do
  so as well:
  
    DB.rollback_prepared_transaction('some string')

* Sequel now supports customizable transaction isolation levels on
  PostgreSQL, MySQL, and Microsoft SQL Server.  You can specify the
  transaction isolation level to use for any transaction using the
  :isolation option with an :uncommitted, :committed, :repeatable,
  or :serializable value:
  
    DB.transaction(:isolation=>:serializable) do ... end
    
  You can also set the default isolation level for transactions via
  the transaction_isolation_level Database attribute:
  
    DB.transaction_isolation_level = :committed
    
  If you are connecting to Microsoft SQL Server, it is recommended
  that you set a default transaction isolation level if you plan
  on using this feature.

* You can specify a NULLS FIRST/LAST ordering by using the
  :nulls=>:first/:last option to asc and desc:
  
    Album.filter(:release_date.desc(:nulls=>:first),
                 :name.asc(:nulls=>:last))
    # ORDER BY release_date DESC NULLS FIRST,
    #          name ASC NULLS LAST

  This syntax is supported by PostgreSQL 8.3+, Firebird 1.5+,
  Oracle, and probably some other databases as well, and makes it
  possible for the user to specify whether NULL values should sort
  before or after other values.

* Sequel::Model.find_or_create now accepts a block that is a yielded
  a new model object to be created if an existing model object is
  not found.  
  
    Node.find_or_create(:name=>'A'){|i| i.parent_id = 4}

* The :frame option for windows and window functions can now be a
  string that is used literally in the SQL.  This is necessary if you
  want to specify a custom frame, such as one that uses a specific
  number of rows preceding or following.

* Savepoints are now supported on H2.

* A :methods_module association option was added, allowing you to
  specify the module into which association instance methods are
  placed.  By default, it uses the module containing the column
  accessor methods.

= Other Improvements

* The :encoding option for the native MySQL adapter should now work
  correctly in all cases.  This fix was included in 3.12.1.

* Sequel now handles arrays of two element arrays automatically when
  using them as the value of a filter hash:
  
    DB[a].filter([:a, :b]=>[[1, 2], [3, 4]])
    
  Previously, you had to call .sql_array on the array in order to
  tell Sequel that it was a value list and not a conditions
  specifier.

* Sequel no longer attempts to use class polymorphism in the
  class_table_inheritance plugin if you don't specify a cti_key.

* When using the native SQLite adapter, prepared statements are now
  cached per connection for increased performance.  Previously,
  Sequel prepared a new statement for every query.

* tinyint(1) columns are now handled as booleans when connecting to
  MySQL via JDBC.
  
* On PostgreSQL, if no :schema option is provided for
  Database#tables, #table_exists?, or #schema, and no default_schema
  is used,  assume all schemas except the default non-public ones.
  Previously, it assumed the public schema for tables and
  table_exists?, but did not assume any schema for #schema.
  
  This fixes issues if you use table names that overlap with table
  names in the information_schema, such as domains.  It's still
  recommended that you specify a default_schema if you are using a
  schema other than public.

* Unsigned integers are now handled correctly in the schema dumper.

* Sequel::SQL::PlaceholderLiteralString is now a GenericExpression
  subclass, allowing you to treat it like most other Sequel
  expression objects:
  
    '(a || ?)'.lit(:b).like('Test%')
    # ((a || b) LIKE 'Test%')

* Sequel now supports the bitwise shift operators (<< and >>) on
  Microsoft SQL Server by emulating them.

* Sequel now supports most bitwise operators (&, |, ^, <<, >>) on H2
  by emulating them.  The bitwise complement operator is not yet
  supported.

* Sequel now logs the SQL queries that are sent when connecting to
  MySQL.

* If a plugin cannot be loaded, Sequel now gives a more detailed
  error message.

= Backwards Compatibility

* Array#sql_array and the Sequel::SQL::SQLArray class are now
  considered deprecated.  Use the Array#sql_value_list and the
  Sequel::SQL::ValueList class instead.  SQLArray is now just
  an alias for ValueList, but it now is an Array subclass instead
  of a Sequel::SQL::Expression subclass.

* Using the ruby bitwise xor operator (^) on PostgreSQL now uses
  PostgreSQL's bitwise xor operator (#) instead of PostgreSQL's
  exponentiation operator (^).  If you want exponentiation, use
  the power function.
  
* Using the ruby bitwise complement operator (~) on MySQL now returns
  a signed integer instead of an unsigned integer, for better
  compatibility with other databases.
  
* Using nil as a case expression value (the 2nd argument to Hash#case
  and Array#case) will now use NULL as the case expression value,
  instead of omitting the case expression value:
  
    # 3.12.0
    {1=>2}.case(0, nil)
    # CASE WHEN 1 THEN 2 ELSE 0 END
    
    # 3.13.0
    {1=>2}.case(0, nil)
    # CASE NULL WHEN 1 THEN 2 ELSE 0 END
    
  In general, you would never use nil explicitly, but the new
  behavior makes more sense if you have a variable that might be nil:
  
    parent_id = Node[1].parent_id
    {1=>2}.case(0, parent_id)

  If parent_id IS NULL/nil, then previously Sequel would have
  generated unexpected SQL.  If you don't want a case expression
  value to be used, do not pass a second argument to #case.
  
* Some internal transaction methods now take an optional options
  hash, so if you have a custom adapter, you will need to make
  changes.
  
* Some internal association methods now take an optional options
  hash.
  
* Some Rakefile task names were modified in the name of consistency:

    spec_coverage -> spec_cov
    integration -> spec_integration
    integration_cov -> spec_integration_cov

---

### Doc Release Notes 3.14.0 (`doc/release_notes/3.14.0.txt`)

= New Features

* Dataset#grep now accepts :all_patterns, :all_columns, and
  :case_insensitive options.  Previously, grep would use a case
  sensitive search where it would match if any pattern matched any
  column.  These three options give you more control over how the
  pattern matching will work:
  
    dataset.grep([:a, :b], %w'%test% foo')
    # WHERE ((a LIKE '%test%') OR (a LIKE 'foo')
    #    OR (b LIKE '%test%') OR (b LIKE 'foo'))

    dataset.grep([:a, :b], %w'%foo% %bar%', :all_patterns=>true)
    # WHERE (((a LIKE '%foo%') OR (b LIKE '%foo%'))
    #   AND ((a LIKE '%bar%') OR (b LIKE '%bar%')))

    dataset.grep([:a, :b], %w'%foo% %bar%', :all_columns=>true)
    # WHERE (((a LIKE '%foo%') OR (a LIKE '%bar%'))
    #   AND ((b LIKE '%foo%') OR (b LIKE '%bar%')))

    dataset.grep([:a, :b], %w'%foo% %bar%',
                 :all_patterns=>true,:all_columns=>true)
    # WHERE ((a LIKE '%foo%') AND (b LIKE '%foo%')
    #   AND (a LIKE '%bar%') AND (b LIKE '%bar%'))
    
    dataset.grep([:a, :b], %w'%test% foo', :case_insensitive=>true)
    # WHERE ((a ILIKE '%test%') OR (a ILIKE 'foo')
    #    OR (b ILIKE '%test%') OR (b ILIKE 'foo')) 

* When using the schema plugin, you can now provide a block to the
  create_table methods to set the schema and create the table
  in the same call:
  
    class Artist < Sequel::Model
      create_table do
        primary_key :id
        String :name
      end
    end

* The tree plugin now accepts a :single_root option, which uses a
  before_save hook to attempt to ensure that there is only a single
  root in the tree.  It also adds a Model.root method to get the
  single root of the tree.
  
* The tree plugin now adds a Model#root? instance method to check
  if the current node is a root of the tree.

* Model#save now takes a :raise_on_failure option which will
  override the object's raise_on_save_failure setting.  This makes
  it easier to get the desired behavior (raise or just return false)
  in library code without using a begin/ensure block.
  
* The Database#adapter_scheme instance method was added, which
  operates the same as the class method.
  
* Sequel now handles the literalization of OCI8::CLOB objects in
  the Oracle adapter.

= Other Improvements

* When using the timezone support, Sequel will now correctly load
  times and datetimes in standard time when the current timezone is
  in daylight time, or vice versa.  Previously, if you tried to
  to load a time or datetime in December when in July in a timezone
  that used daylight time, it would be off by an hour.

* The rcte_tree plugin now works correctly when a :conditions option
  is used.

* The single_table_inheritance plugin now works correctly when the
  class discriminator column has the same name as an existing ruby
  method (such as type).

* Database#each_server now works correctly when a connection string
  is used to connect, instead of an options hash.
  
* Model#destroy now respects the object's use_transactions setting,
  instead of always using a transaction.
  
* Model#exists? now uses a simpler and faster query.

* Sequel now handles the aggregate methods such as count and sum
  correctly on Microsoft SQL Server when using an ordered dataset
  with a clause such as DISTINCT or GROUP and without a limit.
  
* Sequel now handles rename_table correctly on Microsoft SQL Server
  when using a case sensitive collation, or when qualifying the
  table with a schema.

* Sequel now parses the schema correctly on Oracle when the same
  table name is used in multiple schemas.

* Sequel now handles OCIInvalidHandle errors when disconnecting
  in the Oracle adapter.
  
* Sequel now raises a Sequel::Error instead of an ArgumentError
  if the current or target migration version does not exist.
  
* When a mismatched number of composite keys are used in
  associations, Sequel now uses a more detailed error message.

* Significant improvements were made to the Dataset and Model
  RDoc documentation.

= Backwards Compatibility

* Model#valid? now must accept an optional options hash.

* The Model#save_failure private method was renamed to
  raise_hook_failure.
  
* The LOCAL_DATETIME_OFFSET_SECS and LOCAL_DATETIME_OFFSET constants
  have been removed from the Sequel module.
  
* Sequel now uses obj.to_json instead of JSON.generate(obj).  This
  shouldn't affect backwards compatibility, but did fix a bug in
  certain cases.

---

### Doc Release Notes 3.15.0 (`doc/release_notes/3.15.0.txt`)

= Performance Enhancements

* A mysql2 adapter was added to Sequel.  It offers a large (2-6x)
  performance increase over the standard mysql adapter. In order to
  use it, you need to install mysql2, and change your connection
  strings to use mysql2:// instead of mysql://.
  
* Support for sequel_pg was added to the native postgres adapter,
  when pg is being used as the backend.  sequel_pg also offers a
  large (2-6x) performance increase over the default row fetching
  code that the Sequel postgres adapter uses.  In order to use it,
  you just need to install sequel_pg, and the postgres adapter will
  pick it up automatically.
  
* Mass assignment has been made about 10x faster by caching the
  allowed setter methods in the model.

= Other Improvements

* The following construct is now safe to use in environments that
  reload code without unloading existing constants:
  
    class MyModel < Sequel::Model(DB[:table])
    end
    
  Previously, this would raise a superclass mismatch TypeError.

* Sequel now handles the case where both an implicit and an explicit
  table alias are given to join_table, preferring the explicit alias.
  This can happen if you are using models with aliased table names
  and eager graphing them.  Previously, this would result in invalid
  SQL, with both aliases being used.

* You can use use an aliased table for the :join_table option
  of a many_to_many association.

* The active_model plugin now supports the final release of
  ActiveModel 3.0.0.
  
* Typecasting now works correctly for attributes loaded lazily
  when using the lazy_attributes plugin.
  
* The class_table_inheritance plugin now works with non-integer
  primary keys on SQLite.

* Temporary tables are now ignored when parsing the schema on
  PostgreSQL.

* On MySQL, an :auto_increment key with a true value is added to
  the Database#schema output hash if the related column is
  auto incrementing.

* The mysql adapter now handles Mysql::Error exceptions raised when
  disconnecting.

* On SQLite, emulated alter_table commands that require dropping
  the table now preserve the foreign key information, if SQLite
  foreign key support is enabled (it is by default).

* DSN-less connections now work correctly in more cases in the
  ODBC adapter.

* A workaround has been added for a bug in the Microsoft SQL
  Server JDBC Driver 3.0, involving it incorrectly returning a
  smallint instead of a char type for the IS_AUTOINCREMENT
  metadata value.

* An bug in the error handling when connecting to PostgreSQL using
  the do (DataObjects) adapter has been fixed.

= Backwards Compatibility

* The caching of allowed mass assignment methods can result in the
  incorrect exception class being raised if you manually undefine
  instance setter methods in the model class.  If you do this, you
  need to clear the setter methods cache manually:
  
    MyModel.clear_setter_methods_cache

---

### Doc Release Notes 3.16.0 (`doc/release_notes/3.16.0.txt`)

= New Adapter

* A swift adapter was added to Sequel.  Swift is a relatively new
  ruby database library, built on top of a relatively new backend
  called dbic++.  While not yet considered production ready, it is
  very fast.  The swift adapter is about 33% faster and 40% more
  memory efficient for selects than the postgres adapter using pg
  with sequel_pg, though it is slower and less memory efficient
  for inserts and updates.

  Sequel's swift adapter currently supports only PostgreSQL and
  MySQL, but support for other databases will probably be added in
  the future.

= Other Improvements

* Sequel now correctly literalizes DateTime objects on ruby 1.9 for
  databases that support fractional seconds.

* The identity_map plugin now handles composite keys in many_to_one
  associations.

* The rcte_tree plugin now works when the model's dataset does not
  select all columns.  This can happen when using the lazy_attributes
  plugin on the same model.

* Sequel now supports INTERSECT and EXCEPT on Microsoft SQL Server
  2005+.

* The Database#create_language method in the shared PostgreSQL
  adapter now accepts a :replace option to replace the currently
  loaded procedural language if it already exists.  This option
  is ignored for PostgreSQL versions before 9.0.

* The identity_map plugin now handles cases where the plugin is
  loaded separately by two different models.

= Backwards Compatibility

* While not technically backwards compatibility related, it was
  discovered that the identity_map plugin is incompatible with
  the standard eager loading of many_to_many and many_through_many
  associations.  If you want to eagerly load those associations and
  use the identity_map plugin, you should use eager_graph instead
  of eager.

---

### Doc Release Notes 3.17.0 (`doc/release_notes/3.17.0.txt`)

= New Features

* You can now change the level at which Sequel logs SQL statements,
  by calling Database#sql_log_level= with the method name symbol.
  The default is still :info for backwards compatibility. Previously,
  you had to use a proxy logger to get similar capability.

* You can now specify graph aliases where the alias would be the same
  as the table column name using just the table name symbol, instead
  having to repeat the alias as the second element of an array.  More
  clearly:

    # < 3.17.0:
    DB[:a].graph(:b, :a_id=>:id).
      set_graph_aliases(:c=>[:a, :c], :d=>[:b, :d])
    # >= 3.17.0:
    DB[:a].graph(:b, :a_id=>:id).set_graph_aliases(:c=>:a, :d=>:b)
    
  Both of these now yield the SQL:
  
    SELECT a.c, b.d FROM a LEFT OUTER JOIN b ON (b.a_id = a.id)

* You should now be able to connect to MySQL over SSL in the native
  MySQL adapter using the :sslca, :sslkey, and related options.

* Database#views and Database#view_exists? methods were added to the
  Oracle adapter, allowing you to get a an array of view name symbols
  and to check whether a given view exists.

= Other Improvements

* The nested_attributes plugin now avoids unnecessary update calls
  when deleting associated objects, resulting in better performance.

* The optimistic_locking plugin now increments the lock column if no
  other columns were modified but the Model#modified! was called. This
  means it now works correctly with the nested_attributes plugin when
  no changes to the main model object are made.

* The xml_serializer plugin can now round-trip nil values correctly.
  Previously, nil values would be converted into empty strings.  This
  is accomplished by including a nil attribute in the xml tag.
  
* Database#each_server now works correctly when using the jdbc and do
  adapters and a connection string without a separate :adapter option.
  
* You can now clone many_through_many associations.

* The default wait_timeout used by the mysql and mysql2 adapters was
  decreased slightly so that it works correctly with MySQL database
  servers that run on Windows.
  
* Many improvements were made to the AS400 jdbc subadapter.

* Many improvements were made to the swift adapter and subadapters.

* Dataset#ungraphed now removes any cached graph aliases set with
  set_graph_aliases or add_graph_aliases.

---

### Doc Release Notes 3.18.0 (`doc/release_notes/3.18.0.txt`)

= New Features

* Reversible migration support has been added:

    Sequel.migration do
      change do
        create_table(:artists) do
          primary_key :id
          String :name, :null=>false
        end
      end
    end

  The change block acts the same way as an up block, except that
  it automatically creates a down block that reverses the changes.
  So the above is equivalent to:

    Sequel.migration do
      up do
        create_table(:artists) do
          primary_key :id
          String :name, :null=>false
        end
      end
      down do
        drop_table :artists
      end
    end

  The following methods are supported in a change block:
 
  * create_table
  * add_column
  * add_index
  * rename_column
  * rename_table
  * alter_table (supporting the following methods):
    * add_column
    * add_constraint
    * add_foreign_key (with a symbol, not an array)
    * add_primary_key (with a symbol, not an array)
    * add_index
    * add_full_text_index
    * add_spatial_index
    * rename_column

  Use of an other method in a change block will result in the
  creation of a down block that raises an exception.

* A to_dot extension has been added that adds a Dataset#to_dot
  method, which returns a string that can be used as input to
  the graphviz dot program in order to create visualizations
  of the dataset's abstract syntax tree.  Examples:

  * http://sequel.jeremyevans.net/images/to_dot_simple.gif
  * http://sequel.jeremyevans.net/images/to_dot_complex.gif

  Both the to_dot extension and reversible migrations support
  were inspired by Aaron Patterson's recent work on ActiveRecord
  and ARel.

* The user can now control how the connection pool handles attempts
  to access shards that haven't been configured.  The default is
  still to assume the :default shard.  However, you can specify a
  different shard using the :servers_hash option when connecting
  to the database:

    DB = Sequel.connect(..., :servers_hash=>Hash.new(:some_shard))

  You can also use this feature to raise an exception if an
  unconfigured shard is used:

    DB = Sequel.connect(..., :servers_hash=>Hash.new{raise ...})

* The mysql and mysql2 adapters now both support the :read_timeout
  and :connect_timeout options.  read_timeout is the timeout in
  seconds for reading back results of a query, and connect_timeout
  is the timeout in seconds before a connection attempt is abandoned.

= Other Improvements

* The json_serializer plugin will now typecast column values for
  columns with unrestricted setter methods when parsing JSON into
  model objects.  It now also calls the getter method when creating
  the JSON, instead of directly taking the values from the underlying
  hash.

* When parsing the schema for a model with an aliased table name,
  the unaliased table name is now used.

* The SQLite adapter has been updated to not rely on the native
  type_translation support, since that will be removed in the next
  major version of sqlite3-ruby.  Sequel now implements it's own
  type translation in the sqlite adapter, similarly to how the mysql
  and postgres adapters handle type translation.

* On SQLite, when emulating natively unsupported schema methods such
  as drop_column, Sequel will now attempt to recreate applicable
  indexes on the underlying table.

* A more informative error message is now used when connecting fails
  when using the jdbc adapter.

* method_missing is no longer removed from Sequel::BasicObject on
  ruby 1.8.  This should improve compatibility in some cases with
  Rubinius.

= Backwards Compatibility

* On SQLite, Sequel no longer assumes that a plain integer in a
  datetime or timestamp field represents a unix epoch time.

* Previously, saving a model object that used the instance_hooks
  plugin removed all instance hooks.  Now, only the applicable hooks
  are removed.  So if you save a new object, the update instance
  hooks won't be removed.  And if you save an existing object, delete
  instance hooks won't be removed.

* The private Dataset#identifier_list method has been moved into the
  SQLite adapter, since that is the only place it was used.

---

### Doc Release Notes 3.19.0 (`doc/release_notes/3.19.0.txt`)

= New Features

* The add_* association methods now accept a primary key, and
  associates the receiver to the associated model object with that
  primary key:
  
    artist.add_album(42)
    # equivalent to: artist.add_album(Album[42])

* The validation_class_methods plugin now has the ability to
  reflect on validations:
  
    Album.plugin :validation_class_methods
    Album.validates_acceptance_of(:a)
    Album.validation_reflections
    # => {:a=>[[:acceptance, {:tag=>:acceptance, :allow_nil=>true,
                :message=>"is not accepted", :accept=>"1"}]]}

= Other Improvements

* In the postgres, mysql, and sqlite adapters, typecasting now uses
  methods instead of procs.  Since methods aren't closures (while
  procs are), this makes typecasting faster (up to 15%).

* When typecasting model column values, the classes of the new and
  existing values are checked in addition to the values themselves.
  Previously, if the new and existing values were equal (i.e. 1.0
  and 1), it wouldn't update the value.  Now, if the classes are
  different, it always updates the value.

* Date and DateTime objects are now handled correctly when using
  prepared statements/bound variables in the jdbc adapter.
  
* Date, DateTime, Time, true, false, and SQL::Blob objects are now
  handled correctly when using prepared statements/bound variables
  in the sqlite adapter.

* Sequel now uses varbinary(max) instead of image for the generic
  File (blob) type on Microsoft SQL Server.  This makes it possible
  to use an SQL::Blob object as a prepared statement argument.
  
* Sequel now handles blobs better in the Amalgalite adapter.

* When disconnecting a connection using the sqlite adapter, all
  open prepared statements are now closed first.  Previously,
  attempting to disconnect a connection with open prepared statements
  resulted in an error.

* The license file has been renamed from COPYING to MIT-LICENSE, to
  make it easier to determine at a glance which license is used.

= Backwards Compatibility

* Because Sequel switched the generic File type from image to
  varbinary(max) on Microsoft SQL Server, any migrations/schema
  modification methods that used the File type will now result in a
  different column type than before.

* The MYSQL_TYPE_PROCS, PG_TYPE_PROCS, and SQLITE_TYPE_PROCS
  constants have been removed from the mysql, postgres, and sqlite
  adapters, respectively.  The UNIX_EPOCH_TIME_FORMAT and
  FALSE_VALUES constants have also been removed from the sqlite
  adapter.

* Typecasting in the sqlite adapters now uses to_i and to_f instead
  of Integer() and Float() with rescues.  If you put non-numeric
  data in numeric columns on SQLite, this could cause problems.

---

### Doc Release Notes 3.2.0 (`doc/release_notes/3.2.0.txt`)

New Features
------------

* Common table expressions (CTEs) are now supported.  CTEs use the
  SQL WITH clause, and specify inline views that queries can use.
  They also support a recursive mode, where the CTE can recursively
  query its own output, allowing you do do things like load all
  branches for a given node in a plain tree structure.
  
  The standard with takes an alias and a dataset:
  
    DB[:vw].with(:vw, DB[:table].filter{col < 1})
    # WITH vw AS (SELECT * FROM table WHERE col < 1)
    # SELECT * FROM vw
    
  The recursive with takes an alias, a nonrecursive dataset, and a
  recursive dataset:
    
    DB[:vw].with_recursive(:vw,
      DB[:tree].filter(:id=>1),
      DB[:tree].join(:vw, :id=>:parent_id).
                select(:vw__id, :vw__parent_id))
    # WITH RECURSIVE vw AS (SELECT * FROM tree
    #     WHERE (id = 1)
    #     UNION ALL
    #     SELECT vw.id, vw.parent_id
    #     FROM tree
    #     INNER JOIN vw ON (vw.id = tree.parent_id))
    # SELECT * FROM vw

  CTEs are supported by Microsoft SQL Server 2005+, DB2 7+,
  Firebird 2.1+, Oracle 9+, and PostgreSQL 8.4+.
  
* SQL window functions are now supported, and a DSL has been added to
  ease their creation.  Window functions act similarly to aggregate
  functions but operate on sliding ranges of rows.
  
  In virtual row blocks (blocks passed to filter, select, order, etc.)
  you can now provide a block to method calls to change the default
  behavior to create functions that weren't possible previously.  The
  blocks aren't called, but their presence serves as a flag.
  
  What function is created depends on the arguments to the method:
  
  * If there are no arguments, an SQL::Function is created with the
    name of method used, and no arguments.  Previously, it was not
    possible to create functions without arguments using the virtual
    row block DSL.  Example:
    
      DB.dataset.select{version{}} # SELECT version()
    
  * If the first argument is :*, an SQL::Function is created with a
    single wildcard argument (*).  This is mostly useful for count:
    
      DB[:t].select{count(:*){}} # SELECT count(*) FROM t
    
  * If the first argument is :distinct, an SQL::Function is created
    with the keyword DISTINCT prefacing all remaining arguments. This
    is useful for aggregate functions such as count:
    
      DB[:t].select{count(:distinct, col1){}}
      # SELECT count(DISTINCT col1) FROM t
    
  * If the first argument is :over, the second argument, if provided,
    should be a hash of options to pass to SQL::Window.  The options
    hash can also contain :*=>true to use a wildcard argument as the
    function argument, or :args=>... to specify an array of arguments
    to use as the function arguments.

      DB[:t].select{rank(:over){}} # SELECT rank() OVER ()
      DB[:t].select{count(:over, :*=>true){}} # SELECT count(*) OVER ()
      DB[:t].select{sum(:over, :args=>col1,
                    :partition=>col2, :order=>col3){}}
      # SELECT sum(col1) OVER (PARTITION BY col2 ORDER BY col3)
      
  PostgreSQL also supports named windows.  Named windows can be
  specified by Dataset#window, and window functions can reference
  them using the :window option.
  
* Schema information for columns now includes a :ruby_default entry
  which contains a ruby object that represents the default given by
  the database (which is stored in :default).  Not all :default
  entries can be parsed into a :ruby_default, but if the
  schema_dumper extension previously supported it, it should work.

* Methods to create compound datasets (union, intersect, except), now
  take an options hash instead of a true/false flag.  The previous
  API is still supported, but switching to specifying the ALL setting
  using :all=>true is recommended.
  
  Additionally, you can now set :from_self=>false to not wrap the
  returned dataset in a "SELECT * FROM (...)".
  
* Dataset#ungraphed was added that removes the graphing information
  from the dataset.  This allows you to use Dataset#graph for the
  automatic aliasing, or #eager_graph for the automatic aliasing and
  joining, and then remove the graphing information so that the
  resulting objects will not be split into subhashes or associations.

* There were some introspection methods added to Dataset to describe
  which capabilities that dataset does or does not support:
  
    supports_cte?
    supports_distinct_on?
    supports_intersect_except?
    supports_intersect_except_all?
    supports_window_functions?

  In addition to being available for the user to use, these are also
  used internally, so attempting to use a CTE on a dataset that
  doesn't support it will raise an Error.

* Dataset#qualify was added, which is like qualify_to with a default
  of first_source.

  Additionally, qualify now affects PlaceholderLiteralStrings.  It
  doesn't scan the string (as Sequel never attempts to parse SQL),
  but if you provide the column as a symbol placeholder argument, it
  will qualify it.
  
* You can now specify the table and column Sequel::Migrator will use
  to record the current schema version.  The new Migrator.run method
  must be used to use these new options.
  
* The JDBC adapter now accepts :user and :password options, instead
  of requiring them to be specified in the connection string and 
  handled by the JDBC driver.  This should allow connections to
  Oracle using the Thin JDBC driver.
  
* You can now specify the max_connections, pool_timeout, and
  single_threaded settings directly in the connection string:
  
    postgres:///database?single_threaded=t
    postgres:///database?max_connections=10&pool_timeout=20

* Dataset#on_duplicate_key_update now affects Dataset#insert when
  using MySQL.

* You can now specify the :opclass option when creating PostgreSQL
  indexes.  Currently, this only supports a single operator class
  for all columns.  If you need different operator classes per
  column, please post on sequel-talk.
  
* Model#autoincrementing_primary_key was added and can be used if
  the autoincrementing key isn't the same as the primary key.  The
  only likely use for this is on MySQL MyISAM tables with composite
  primary keys where only one of the composite parts is
  autoincrementing.

* You can now use database column values as search patterns and
  specify the text to search as a String or Regexp:
  
    String.send(:include, Sequel::SQL::StringMethods)
    Regexp.send(:include, Sequel::SQL::StringMethods)

    'a'.like(:x)  # ('a' LIKE x)
    /a/.like(:x)  # ('a' ~ x)
    /a/i.like(:x) # ('a' ~* x)
    /a/.like(:x, 'b') # (('a' ~ x) OR ('a' ~ 'b'))

* The Dataset#dataset_alias private method was added.  It can be
  overridden if you have tables named t0, t1, etc., and want to make
  sure the default dataset aliases that Sequel uses do not clash
  with existing table names.
  
* Sequel now raises an Error if you call Sequel.connect with
  something that is not a Hash or String.
  
* bin/sequel now accepts a -N option to not test the database
  connection.
  
* An opening_databases.rdoc file was added to the documentation
  directory, which should be a good introduction for new users about
  how to set up your Database connection.

Other Improvements
------------------

* MySQL native adapter SELECT is much faster than before, up to 75%
  faster.

* JDBC SELECT is about 10% faster than before.  It's still much
  slower than the native adapters, due to conversion issues.

* bin/sequel now works with a YAML file on ruby 1.9.

* MySQL foreign key table constraints have been fixed.

* Database#indexes now works on PostgreSQL if the schema used is a
  Symbol.  It also works on PostgreSQL versions all the way back to
  7.4.

* Graphing of datasets with dataset sources has been fixed.

* Changing a columns name, type, or NULL status on MySQL now
  supports a much wider selection of column defaults.
  
* The stored procedure code is now thread-safe.  Sequel is
  thread-safe in general, but due to a bug the previous stored 
  procedure code was not thread-safe.

* The ODBC adapter now drops statements automatically instead of
  requiring the user to do so manually, making it more similar
  to other adapters.

* The single_table_inheritance plugin no longer overwrites the STI
  field if the field already has a value.  This allows you to use
  create in the generic class to insert a value that will be
  returned as a subclass:
  
    Person.create(:kind => "Manager")
    
* When altering columns on MySQL, :unsigned, :elements, :size and other
  options given are no longer ignored.

* The PostgreSQL shared adapter's explain and analyze methods have
  been fixed, they had been broken in 3.0.
  
* Parsing of the server's version is more robust on PostgreSQL.
  It should now work correctly for 8.4 and 8.4rc1 type versions.

Backwards Compatibility
-----------------------

* Dataset#table_exists? has been removed, since it never worked
  perfectly.  Use Database#table_exists? instead.
  
* Model.grep now calls Dataset#grep instead of Enumerable#grep.
  If you are using Model.grep, you need to modify your application.

* The MSSQL shared adapter previously used the :with option for
  storing the NOLOCK setting of the query.  That option has been
  renamed to :table_options, since :with is now used for CTEs.
  This should not have an effect unless you where using the option
  manually.

* Previously, providing a block to a method calls in virtual row
  blocks did not change behavior, where now it causes a different
  code path to be used.  In both cases, the block is not evaluated,
  but that may change in a future version.
  
* Dataset#to_table_reference protected method was removed, as it was
  no longer used.
  
* The pool_timeout setting is now converted to an Integer, so if you
  used to pass in a Float, it no longer works the same way.
  
* Most files in adapters/utils have been removed, in favor of 
  integrating the code directly into Database and Dataset.  If you
  were previously checking for the UnsupportedIntersectExcept or
  related modules, use the Dataset introspection methods instead
  (e.g. supports_intersect_except?).
  
* If you were using the ODBC adapter and manually dropping returned
  statements, you should note that now statements are dropped
  automatically, and the execute method doesn't return a statement
  object.
  
* The MySQL adapter on_duplicate_key_update_sql is now a private
  method.
  
* If you were modifying the :from dataset option directly, note that
  Sequel now expects this option to be preprocessed.  See the new
  implementation of Dataset#from for an idea of the changes
  required.
  
* Dataset#simple_select_all? now returns false instead of true for a
  dataset that selects from another dataset.

---

### Doc Release Notes 3.20.0 (`doc/release_notes/3.20.0.txt`)

= New Features

* The swift adapter now supports an SQLite subadapter.  Use the
  :db_type => 'sqlite' option when connecting.  You can use an
  in memory database with the following connection string:
  
    swift:///?database=:memory:&db_type=sqlite

* Arbitrary JDBC properties can now be set in the JDBC adapter
  using the :jdbc_properties option when connecting.  The value
  of this option should be a hash where keys and values are JDBC
  property keys and values.
  
* Basic Microsoft Access support was added to the ado adapter.
  The creation of autoincrementing primary key integers now works,
  and identifiers are now quoted with [].

* The Database#indexes method now supports a :partial option when
  connecting to MySQL, which makes it include partial indexes (which
  are usually excluded).

= Other Improvements

* The class_table_inheritance plugin now handles subclass
  associations better.  Previously, the implicit eager loading code
  had issues when you called an association method that only existed
  in the subclass.

* The error message used when a validates_max_length validation is
  applied to a nil column value has been improved.  You can override
  the message yourself using the :nil_message option.
  
* The read_timeout and connect_timeout options now work correctly in
  the mysql adapter.

* Another MySQL disconnect error message is now recognized.

= Backwards Compatibility

* The swift adapter was upgraded to support swift 0.8.1.  Older
  versions of swift are no longer supported.

---

### Doc Release Notes 3.21.0 (`doc/release_notes/3.21.0.txt`)

= New Features

* A tinytds adapter was added, enabling Sequel users on a C-based
  ruby running on *nix easy access to Microsoft SQL Server.
  Previously, the best way to connect to Microsoft SQL Server from
  a C-based ruby on *nix was to use the ODBC adapter with unixodbc
  and freetds.  However, setting that up is nontrivial, while
  setting up tinytds is very easy.
  
  Note that the tinytds adapter currently requires the git master
  branch of tiny_tds, but tiny_tds 0.4.0 should include the related
  changes.
  
* An association_autoreloading plugin has been added to Sequel,
  which removes stale many_to_one associations from the cache when
  the associated foreign key setter is used to change the value of
  the foreign key.

* bin/sequel now operates more like a standard *nix utility.
  If given a file on the command line after the connection
  string, it will assume that file has ruby code and load it.
  If stdin is not a tty, it will read from stdin and execute it
  as ruby code.
  
  For recent Linux users, this means you can have a shebang line
  such as:
  
    #!/usr/bin/sequel postgres://user:pass@host/db
    
  to create a self contained script.

* bin/sequel now supports -r and -I options similar to ruby's
  -r and -I options.
  
* MySQL datasets now have a calc_found_rows method that uses
  SQL_CALC_FOUND_ROWS, which provides a fast way to limit the
  number of results returned by a dataset while having an easy
  way to determine how many rows would have been returned if no
  limit was applied.

= Other Improvements

* The Sequel::Model.plugin method can now be overridden just like
  any other method.  Previously, it was the only method that
  was defined directly on the class.  This allows the creation
  of plugins that can modify the plugin system itself.

* Symbol splitting (:table__column___alias) now works correctly
  for identifiers that include characters that aren't in [\w ].
  Among other things, this means that identifiers with accented
  characters or even kanji characters can be used with symbol
  splitting.
  
* If cover? is defined, it is now used in preference to include?
  for the validates_includes/validates_inclusion_of validations.
  ruby 1.9 defines include? differently for some ranges and can
  be very slow, while cover? is similar to the 1.8 behavior of
  just checking the beginning and end of the range.
  
* The bin/sequel -L option now takes effect even if the -m,
  -C, -d, or -D options are used.
  
* The schema_dumper extension now recognizes the "bigint unsigned"
  type.
  
* On Microsoft SQL Server, if joining to a subselect that uses a
  common table expression, that common table expression is
  promoted to the main dataset.  This allows most queries to work
  correctly, but is vulnerable to issues if both the current
  dataset and the joined dataset use common table expressions with
  the same name.  Unfortunately, unlike PostgreSQL, Microsoft SQL
  Server does not allow common table expressions to occur in
  subselects.

* The NULL/NOT NULL, DEFAULT, and UNIQUE column options now
  use the proper order on H2 and Oracle, so they can now be
  used in conjunction with each other.
  
* Row locks are now enabled on Oracle.

* The join_table method on MySQL no longer ignores the block it was
  given.
  
* The informix adapter now supports ruby-informix version >= 0.7.3,
  while still being backwards compatible with older versions.

* The specs now run under both RSpec 2 and RSpec 1.

---

### Doc Release Notes 3.22.0 (`doc/release_notes/3.22.0.txt`)

= New Features

* Support COLLATE in column definitions.  At least MySQL and Microsoft
  SQL Server support them, and PostgreSQL 9.1 should as well.

* When connecting to Microsoft SQL Server, you can use the
  mssql_unicode_strings accessor to turn of the default usage
  of unicode strings (N'') and use regular strings (''). This
  can improve performance, but changes the behavior.  It's
  set to true by default for backwards compatibility.  You can
  change it at both the dataset and database level:

    DB.mssql_unicode_strings = false # default for datasets
    dataset.mssql_unicode_strings = false # just this dataset

* In the oracle adapter, if Sequel.application_timezone is :utc, set
  the timezone for the connection to use the 00:00 timezone.

= Other Improvements

* In the single_table_inheritance plugin, correctly handle a
  multi-level class hierarchy so that loading instances from a
  middle level of the hierarchy can return instances of subclasses.

* Don't use a schema when creating a temporary table, even if
  default_schema is set.

* Fix the migrator when a default_schema is used.

* In the ado adapter, assume a connection to SQL Server if the
  :conn_string is given and doesn't indicate Access/Jet.

* Fix fetching rows in the tinytds adapter when the
  identifier_output_method is nil.

* The tinytds adapter now checks for disconnect errors, but it might
  not be reliable until the next release of tiny_tds.

* The odbc adapter now handles ODBC::Time instances correctly.

---

### Doc Release Notes 3.23.0 (`doc/release_notes/3.23.0.txt`)

= New Features

* Sequel now allows dynamic customization for eager loading.
  Previously, the parameters for eager loading were fixed at
  association creation time.  Now, they can be modified at query
  time.  To dynamically modify an eager load, you use a hash with
  the proc as the value. For example, if you have this code:

    Artist.eager(:albums)

  And you only want to eagerly load albums where the id is greater
  than or equal to some number provided by the user, you do:

    min = params[:min].to_i
    Artist.eager(:albums=>proc{|ds| ds.where{id > min}})
    
  This also works when eager loading via eager_graph:
  
    Artist.eager_graph(:albums=>proc{|ds| ds.where{id > min}})
  
  For eager_graph, the dataset is the dataset to graph into the
  current dataset, and filtering it will result in an SQL query
  that joins to a subquery.
  
  You can also use dynamic customization while cascading to also
  eagerly load dependent associations, by making the hash value
  a single entry hash with a proc key and the value being the
  dependent associations to eagerly load. For example, if you want
  to eagerly load tracks for those albums:

    Artist.eager(:albums=>{proc{|ds| ds.where{id > min}}=>:tracks})

* Sequel also now allows dynamic customization for regular
  association loading.  Previously, this was possible by using the
  association's dataset:

    albums = artist.albums_dataset.filter{id > min}

  However, then there was no handling of caching, callbacks, or
  reciprocals.  For example:

    albums.each{|album| album.artist}
    
  Would issue one query per album to get the artist, because the
  reciprocal association was not set.  Now you can provide a
  block to the association method:
  
    albums = artist.albums{|ds| ds.filter{id > min}}
    
  This block is called with the dataset used to retrieve the
  associated objects, and should return a modified version of that
  dataset.
  
  Note that ruby 1.8.6 doesn't allow blocks to take block arguments,
  so you have to pass the block as a separate proc argument to the
  association method if you are still using 1.8.6.

* Sequel now supports filtering by associations.  This wasn't
  previously supported as filtering is a dataset level feature and
  associations are a model level feature, and datasets do not depend
  on models.  Now, model datasets have the ability to filter by
  associations.  For example, to get all albums for a given artist,
  you could do:
  
    artist = Artist[1]
    Album.filter(:artist=>artist)
    
  Since the above can also be accomplished with:
  
    artist.albums
    
  this may not seem like a big improvement, but it allows you to
  filter on multiple associations simultaneously:
  
    Album.filter(:artist=>artist, :publisher=>publisher)
    
  For simple many_to_one associations, the above is just a simpler
  way to do:
  
    Album.filter(:artist_id=>artist.id, :publisher_id=>publisher.id)
    
  Sequel supports this for all association types, including
  many_to_many and many_through_many, where a subquery is used, and
  it also works when composite key associations are used:
  
    Album.filter(:artist=>artist, :tags=>tag)
    
  This will give you the albums for that artist that are also tagged
  with that tag.  To provide multiple values for the same
  association, mostly useful for many_to_many associations, you can
  either use separate filter calls or specify the conditions as an
  array:
  
    Album.filter(:tags=>tag1).filter(:tags=>tag2)
    Album.filter([[:tags, tag1], [:tags, tag2]])

* A columns_introspection extension has been added that makes
  datasets attempt to guess their columns in some cases instead of
  issuing a database query.  This can improve performance in cases
  where the columns are needed implicitly, such as graphing.  After
  loading the extension, you can enable the support for specific
  datasets by extending them with Sequel::ColumnIntrospection.  To
  enable introspection for all datasets, use:
  
    Sequel::Dataset.introspect_all_columns

* A serialization_modification_detection plugin has been added.
  Previously, Sequel could not detect modifications made to
  serialized objects.  It could detect modification if you assigned
  a new value:
  
    model.hash_column = model.hash_column.merge(:foo=>:bar)
    
  but not if you just modified the object directly:
  
    model.hash_columns[:foo] = :bar
    
  With this plugin, such modifications can be detected, at a
  potentially significant performance cost.

= Other Improvements

* When using a migration directory containing both older integer
  migrations and newer timestamp migrations, where some integer
  migrations have not been applied, make sure to apply the remaining
  integer migrations before the timestamp migrations.  Previously,
  they could be applied out of order due to a lexicographic sort
  being used instead of a numeric sort.

* If a model does not select all columns from its table, the
  insert_select optimization is no longer used.  Previously,
  creating a new model object for such a model could result in the
  object containing columns that the model does not select.

* You can now use :select=>[] as an option for many_to_many
  associations to select all columns from both the associated
  table and the join table.  Previously, this raised an error and
  required you do :select=>'*'.lit as a workaround.  The default
  remains to select all columns in the associated table and none
  from the join table.

* The xml_serializer plugin now handles namespaced models by
  using __ instead of / as the namespace separator.  Previously, /
  was used and caused problems as it is not valid XML.
  
* The :eager_grapher association option can now accept a proc that
  takes a single hash of options instead of a fixed 3 arguments.
  This is the recommended way going forward of writing custom
  :eager_graphers, and all of the internal ones have been converted.
  The previous way of using 3 arguments is still supported.
  
* A bug in the identity_map plugin for many_to_one associations
  without full association reflection information has been fixed.

* Sequel is now using GitHub Issues for issue tracking.  Old issues
  have been migrated from Google Code.

= Backwards Compatibility

* The filter by associations support breaks backward compatibility for
  users who previously added an sql_literal instance method to
  Sequel::Model.  Usually, that was done to for reasons similar to
  but inferior than the filter by association support.  The following
  code can be used as a temporary workaround until you can modify
  your program to use the new filter by associations support:
  
    Sequel::Model::Associations::DatasetMethods.
      send(:remove_method, :complex_expression_sql)

* The private Sequel::Model#_load_associated_objects method now takes
  an additional, optional options hash.  Plugins that override that
  method need to be modified.

---

### Doc Release Notes 3.24.0 (`doc/release_notes/3.24.0.txt`)

= Prepared Statement Plugins

* The prepared_statements plugin makes Sequel::Model classes use
  prepared statements for creating, updating, and destroying model
  instances, as well as looking up model objects by primary key.
  With this plugin, all of the following will use prepared
  statements:
  
    Artist.plugin :prepared_statements
    Artist.create(:name=>'Foo')
    a = Artist[1]
    a.update(:name=>'Bar')
    a.destroy

* The prepared_statements_safe plugin reduces the number of
  prepared statements that can be created by doing two things. First,
  it makes the INSERT statements used when creating instances to use
  as many columns as possible, setting specific values for all
  columns with parseable default values.  Second, it changes
  save_changes to just use save, saving all columns instead of just
  the changed ones.

  The reason for this plugin is that Sequel's default behavior of
  using only the values specifically set when creating instances
  and having update only set changed columns by default can lead
  to a large number of prepared statements being created.
  
  For prepared statements to be used, each set of columns in the
  insert and update statements needs to have its own prepared
  statement.  If you have a table with 1 primary key column and
  4 other columns, you can have up to 2^4 = 16 prepared statements
  created, one for each subset of the 4 columns.  If you have 1
  primary key column and 20 other columns, there are over a million
  subsets, and you could hit your database limit for prepared
  statements (a denial of service attack).
  
  Using the prepared_statements_safe plugin mitigates this
  issue by reducing the number of columns that may or may not be
  present in the query, in many cases making sure that each model
  will only have a single INSERT and a single UPDATE prepared
  statement.

* The prepared_statements_associations plugin allows normal
  association method calls to use prepared statements if possible.
  For example:
  
    Artist.plugin :prepared_statements_associations
    Artist.many_to_one :albums
    Artist[1].albums
  
  Will use a prepared statement to return the albums for that artist.
  This plugin works for all supported association types.  There are
  some associations (filtered and custom associations) that Sequel
  cannot currently use a prepared statement reliably, for those
  Sequel will use a regular query.

* The prepared_statements_with_pk plugin allows the new
  Dataset#with_pk method (explained below) to use prepared statements.
  For example:
  
    Artist.plugin :prepared_statements_with_pk
    Artist.filter(...).with_pk(1)
  
  Will use a prepared statement for this query.  The most benefit
  from prepared statements come from queries that are expensive to
  parse and plan but quick to execute, so using this plugin with
  a complex filter can in certain cases yield significant performance
  improvements.
    
  However, this plugin should be considered unsafe as it is possible
  that it will create an unbounded number of prepared statements. It
  extracts parameters from the dataset using Dataset#unbind
  (explained below), so if your code has conditions that vary per
  query but that Dataset#unbind does not handle, an unbounded number
  of prepared statements can be created.  For example:
  
    Artist.filter(:a=>params[:b].to_i).with_pk[1]
    Artist.exclude{a > params[:b].to_i}.with_pk[1]
    
  are safe, but:
  
    Artist.filter(:a=>[1, params[:b].to_i]).with_pk[1]
    Artist.exclude{a > params[:b].to_i + 2}.with_pk[1]
    
  are not.  For queries that are not safe, Dataset#with_pk should
  not be used with this plugin, you should switch to looking up by
  primary key manually (for a regular query):
  
    Artist.filter(:a=>[1, params[:b].to_i])[:id=>1]
  
  or using the prepared statement API to create a custom prepared
  statement:
  
    # PS = {}
    PS[:name] ||= Artist.filter(:a=>[1, :$b], :id=>:$id).
           prepare(:select, :name)
    PS[:name].call(:b=>params[:b].to_i, :id=>1)
    
= Other New Features

* Filtering by associations got a lot more powerful.  Sequel 3.23.0
  introduced filtering by associations:
  
    Album.filter(:artist=>artist)
    
  This capability is much expanded in 3.24.0, allowing you to
  exclude by associations:
  
    Album.exclude(:artist=>artist)
    
  This will match all albums not by that artist.
    
  You can also filter or exclude by multiple associated objects:
  
    Album.filter(:artist=>[artist1, artist2])
    Album.exclude(:artist=>[artist1, artist2])
    
  The filtered dataset will match all albums by either of those
  two artists, and the excluded dataset will match all albums not
  by either of those two artists.
  
  You can also filter or exclude by using a model dataset:
  
    Album.filter(:artist=>Artist.filter(:name.like('A%'))).all
    Album.exclude(:artist=>Artist.filter(:name.like('A%'))).all
    
  Here the filtered dataset will match all albums where the
  associated artist has a name that begins with A, and the excluded
  dataset will match all albums where the associated artist does not
  have a name that begins with A.
  
  All of these types of filtering and excluding work with all of
  association types that ship with Sequel, even the many_through_many
  plugin.

* Sequel now supports around hooks, which wrap the related before
  hook, behavior, and after hook.  Like other Sequel hooks, these
  are implemented as instance methods.  For example, if you wanted
  to log DatabaseErrors raised during save:

    class Artist < Sequel::Model
      def around_save
        super
      rescue Sequel::DatabaseError => e
        # log the error
        raise
      end
    end
    
  All around hooks should call super, not yield.  If an around hook
  doesn't call super or yield, it is treated as a hook failure,
  similar to before hooks returning false.
  
  For around_validation, the return value of super should be whether
  the object is valid.  For other around hooks, the return value of
  super is currently true, but it's possible that will change in the
  future.
  
* Dataset#with_pk has been added to model datasets that allows you
  to find the object with the matching primary key:
  
    Artist.filter(:name.like('A%')).with_pk(1)
    
  This should make easier the common case where you want to find
  a particular object that is associated to another object:
  
    Artist[1].albums_dataset.with_pk(2)

  Before, there was no way to do that without manually specifying
  the primary key:
  
    Artist[1].albums_dataset[:id=>2]
    
  To use a composite primary key with with_pk, you have to provide
  an array:
  
    Artist[1].albums_dataset.with_pk([1, 2])
    
* Dataset#[] for model datasets will now call with_pk if given a
  single Integer argument.  This makes the above case even easier:
  
    Artist[1].albums_dataset[2]
    
  Note that for backwards compatibility, this only works for
  single integer primary keys.  If you have a composite primary key
  or a string/varchar primary key, you have to use with_pk.

* Dataset#unbind has been added, which allows you to take a dataset
  that uses static bound values and convert them to placeholders.
  Currently, the only cases handled are SQL::ComplexExpression
  objects that use a =, !=, <, >, <=, or >= operator where the first
  argument is a Symbol, SQL::Identifier, or
  SQL::QualifiedIdentifier, and the second argument is a Numeric,
  String, Date, or Time.  Dataset#unbind returns a two element array,
  where the first element is a modified copy of the receiver, and the
  second element is a bound variable hash:
  
    ds, bv = DB[:table].filter(:a=>1).unbind
    ds # DB[:table].filter(:a=>:$a)
    bv # {:a=>1}

  The purpose of doing this is that you can then use prepare or call
  on the returned dataset with the returned bound variables:
  
    ds.call(:select, bv)
    # SELECT * FROM table WHERE (a = ?); [1]
    
    ps = ds.prepare(:select, :ps_name)
    # PREPARE ps_name AS SELECT * FROM table WHERE (a = ?)
    ps.call(bv)
    # EXECUTE ps_name(1)
    
  Basically, Dataset#unbind takes a specific statement and attempts
  to turn it into a generic statement, along with the placeholder
  values it extracted.
  
  Unfortunately, Dataset#unbind cannot handle all cases.  For
  example:
  
    DB[:table].filter{a + 1 > 10}.unbind
    
  will not unbind any values.  Also, if you have a query with
  multiple different values for a variable, it will raise an
  UnbindDuplicate exception:
  
    DB[:table].filter(:a=>1).or(:a=>2).unbind

* A defaults_setter plugin has been added that makes it easy to
  automatically set default values when creating new objects.  This
  plugin makes Sequel::Model behave more like ActiveRecord in that
  new model instances (before saving) will have default values
  parsed from the database.  Unlike ActiveRecord, only values with
  non-NULL defaults are set.  Also, Sequel allows you to easily
  modify the default values used:
  
    Album.plugin :default_values
    Album.new.values # {:copies_sold => 0}
    Album.default_values[:copies_sold] = 42
    Album.new.values # {:copies_sold => 42}
    
  Before, this was commonly done in an after_initialize hook, but
  that's slower as it is also called for model instances loaded from
  the database.
  
* A Database#views method has been added that returns an array
  of symbols representing view names in the database.  This works
  just like Database#tables except it returns views.

* A Sequel::ASTTransformer class was added that makes it easy to
  write custom transformers of Sequel's internal abstract syntax
  trees.  Dataset#qualify now uses a subclass of ASTTransformer to do
  its transformations, as does the new Dataset#unbind.

= Other Improvements

* Database#create_table? now uses a single query with IF NOT EXISTS
  if the database supports such syntax.  Previously, it issued a
  SELECT query to determine table existence.  Sequel currently
  supports this syntax on MySQL, H2, and SQLite 3.3.0+.
  
  The Database#supports_create_table_if_not_exists? method was added
  to allow users to determine whether this syntax is supported.

* Multiple column IN/NOT IN emulation now works correctly with
  model datasets (or other datasets that use a row_proc).
  
* You can now correctly invert SQL::Constant instances:

    Sequel::NULL # NULL
    ~Sequel::NULL # NOT NULL
    Sequel::TRUE # TRUE
    ~Sequel::TRUE # FALSE

* A bug in the association_pks plugin has been fixed in the case
  where the associated table had a different primary key column name
  than the current table.

* The emulated prepared statement support now supports nil and false
  as bound values.
  
* The to_dot extension was refactored for greater readability.  The
  only change was a small fix in the display for SQL::Subscript
  instances.

* The Dataset#supports_insert_select? method is now available to let
  you know if the dataset supports insert_select.  You should use
  this method instead of respond_to? for checking for insert_select
  support.
  
* Prepared statements/bound variable can now use a new :insert_select
  type for preparing a statement that will insert a row and return
  the row inserted, if the dataset supports insert_select.
  
* The Model#initialize_set private method now exists for easier plugin
  writing.  It is only called for new model objects, with the hash
  given to initialize.  By default, it just calls set.
  
* A small bug when creating anonymous subclasses of Sequel::Model on
  ruby 1.9 has been fixed.
  
* If Thread#kill is used inside a transaction on ruby 1.8 or
  rubinius, the transaction is rolled back.  This situation is not
  handled correctly on JRuby or ruby 1.9, and I'm not sure it's
  possible to handle correctly on those implementations.
  
* The postgres adapter now supports the
  Sequel::Postgres::PG_NAMED_TYPES hash for associating conversion
  procs for custom types that don't necessarily have the same type
  oid on different databases.  This hash uses symbol keys and
  proc values:
  
    Sequel::Postgres::PG_NAMED_TYPES[:interval] = proc{|v| ...}
    
  The conversion procs now use a separate hash per Database object
  instead of a hash shared across all Database objects.  You
  can now modify the types for a particular Database object, but
  you have to use the type oid:
  
    DB.conversion_procs[42] = proc{|v| ...}

* On SQLite and MSSQL, literalization of true and false values given
  directly to Dataset#filter has been fixed.  So the following now
  works correctly on those databases:
  
    DB[:table].filter(true)
    DB[:table].filter(false)
    
  Unfortunately, because SQLite and MSSQL don't have a real boolean
  type, these will not work:
  
    DB[:table].filter{a & true}
    DB[:table].filter{a & false}
    
  You currently have to work around the issue by doing:
  
    DB[:table].filter{a & Sequel::TRUE}
    DB[:table].filter{a & Sequel::FALSE}
    
  It is possible that a future version of Sequel will remove the need
  for this workaround, but that requires having a separate
  literalization method specific to filters.

* The MySQL bit type is no longer treated as a boolean.  On MySQL, the
  bit type is a bitfield, which is very different than the MSSQL bit
  type, which is the closest thing to a boolean on MSSQL.
  
* The bool database type is now recognized as a boolean.  Some SQLite
  databases use bool, such as the ones used in Firefox.
  
* SQL_AUTO_IS_NULL=0 is now set by default when connecting to MySQL
  using the swift or jdbc adapters.  Previously, it was only set by
  default when using the mysql or mysql2 adapters.

* Dataset#limit now works correctly on Access, using the TOP syntax.

* Dataset#limit now works correctly on DB2, using the FETCH FIRST
  syntax.
    
* The jdbc mssql subadapter was split into separate subadapters for
  sqlserver (using Microsoft's driver) and jtds (using the open
  source JTDS driver).

* The jdbc jtds subadapter now supports converting Java CLOB
  objects to ruby strings.

* Tables from the INFORMATION_SCHEMA are now ignored when parsing
  schema on JDBC.

* The informix adapter has been split into shared/specific parts, and
  a jdbc informix subadapter has been added.

* Dataset#insert_select now works correctly on MSSQL when the core
  extensions are disabled.

* The sqlite adapter now logs when preparing a statement.

* You no longer need to be a PostgreSQL superuser to run the postgres
  adapter specs.
  
* The connection pool specs are now about 10 times faster and not
  subject to race conditions due to using Queues instead of
  sleeping.

= Backwards Compatibility

* Model#save no longer calls Model#valid?.  It now calls the
  Model#_valid? private method that Model#valid? also calls.  To mark
  a model instance invalid, you should override the Model#validate
  method and add validation errors to the object.

* The BeforeHookFailure exception class has been renamed to
  HookFailure since hook failures can now be raised by around hooks
  that don't call super.  BeforeHookFailure is now an alias to
  HookFailure, so no code should break, but you should update your
  code to reflect the new name.

* Any custom argument mappers used for prepared statements now need
  to implement the prepared_arg? private instance method and have it
  return true.

* If your databases uses bit as a boolean type and isn't MSSQL, it's
  possible that those columns will no longer be treated as booleans.
  Please report such an issue on the bugtracker.
  
* It is possible that the filtering and excluding by association
  datasets will break backwards compatibility in some apps.  This can
  only occur if you are using a symbol with the same name as an
  association with a model dataset whose model is the same as the
  associated class.  As associations almost never have the same names
  as columns, this would require either aliasing or joining to
  another table.  If for some reason this does break your app, you
  can work around it by changing the symbol to an SQL::Identifier or
  a literal string.

* The Sequel::Postgres.use_iso_date_format= method now only affects
  future Database objects.

* On MySQL, Database#tables no longer returns view names, it only
  returns table names.  You have to use Database#views to get view
  names now.

---

### Doc Release Notes 3.25.0 (`doc/release_notes/3.25.0.txt`)

= New Features

* drop_table, drop_view, drop_column, and drop_constraint all now
  support a :cascade option for using CASCADE.
  
    DB.drop_table(:tab, :cascade=>true)
    # DROP TABLE tab CASCADE
    
    DB.drop_column(:tab, :col, :cascade=>true)
    # ALTER TABLE tab DROP COLUMN col CASCADE
    
  A few databases support CASCADE for dropping tables and views,
  but only PostgreSQL appears to support it for columns and
  constraints.  Using the :cascade option when the underlying
  database doesn't support it will probably result in a
  DatabaseError being raised.

* You can now use datasets as expressions, allowing things such as:
  
    DB[:table1].select(:column1) > DB[:table2].select(:column2)
    # (SELECT column1 FROM table1) > (SELECT column2 FROM table2)

    DB[:table1].select(:column1).cast(Integer)
    # CAST((SELECT column1 FROM table1) AS integer)

* Dataset#select_group has been added for grouping and selecting on
  the same columns.
  
    DB[:a].select_group(:b, :c)
    # SELECT b, c FROM a GROUP BY b, c

* Dataset#exclude_where and #exclude_having methods have been added,
  allowing you to specify which clause to affect.  #exclude's
  behavior is still to add to the HAVING clause if one is present,
  and use the WHERE clause otherwise.
  
* Dataset#select_all now accepts optional arguments and will select
  all columns from those arguments if present:
  
    DB[:a].select_all(:a)
    # SELECT a.* FROM a
    
    DB.from(:a, :b).select_all(:a, :b)
    # SELECT a.*, b.* FROM a, b

* Dataset#group and #group_and_count now both accept virtual row
  blocks:
  
    DB[:a].select(:b).group{c(d)}
    # SELECT b FROM a GROUP BY c(d)

* If you use a LiteralString as a validation error message, 
  Errors#full_messages will now not add the related column name to
  the start of the error message.

* Model.set_dataset now accepts SQL::Identifier,
  SQL::QualifiedIdentifier, and SQL::AliasedExpression instances,
  treating them like Symbols.
  
= Other Improvements

* The association_pks plugin's setter method will now automatically
  convert a given array of strings to an array of integers if the
  primary key field is an integer field, which should make it easier
  to use in web applications.
  
* nil bound variable, prepared statement, and stored procedure
  arguments are now handled correctly in the JDBC adapter.

* On 1.9, you can now load plugins even when ::ClassMethods,
  ::InstanceMethods, or ::DatasetMethods is defined.

= Backwards Compatibility

* The tinytds adapter now only works with tiny_tds 0.4.5 and greater.
  Also, if you were using the tinytds adapter with FreeTDS 0.91rc1,
  you need to upgrade to FreeTDS 0.91rc2 for it to work.  Also, if
  you were referencing an entry in the freetds.conf file, you now
  need to specify it directly using the :dataserver option when
  connecting, the adapter no longer copies the :host option to the
  :dataserver option.

* On postgresql, Sequel now no longer drops tables with CASCADE by
  default.  You now have to use the :cascade option to drop_table if
  you want to use CASCADE.

* The Database#drop_table_sql private method now takes an additional
  options hash argument.

---

### Doc Release Notes 3.26.0 (`doc/release_notes/3.26.0.txt`)

= Performance Enhancements

* The internal implementation of eager_graph has been made 75% to
  225% faster than before, with greater benefits to more complex
  graphs.

* Dataset creation has been made much faster (2.5x on 1.8 and 4.4x on
  1.9), and dataset cloning has been made significantly faster (40%
  on 1.8 and 20% on 1.9).

= Other Improvements

* Strings passed to setter methods for integer columns are no longer
  considered to be in octal format if they include leading zeroes.
  The previous behavior was never intended, but was a side effect of
  using Kernel#Integer.  Strings with leading zeroes are now treated
  as decimal, and you can still use the 0x prefix to treat them as
  hexadecimal.  If anyone was relying on the old octal behavior, let
  me know and I'll add an extension that restores the octal behavior.
  
* The identity_map plugin now works with the standard eager loading
  of many_to_many and many_through_many associations.
  
* Database#create_table! now only attempts to drop the table if it
  already exists.  Previously, it attempted to drop the table
  unconditionally ignoring any errors, which resulted in misleading
  error messages if dropping the table raised an error caused by
  permissions or referential integrity issues.

* The default connection pool now correctly handles the case where a
  disconnect error is raised and an exception is raised while
  running the disconnection proc.
  
* Disconnection errors are now detected when issuing transaction
  statements such as BEGIN/ROLLBACK/COMMIT.  Previously, these
  statements did not handle disconnect errors on most adapters.
  
* More disconnection errors are now detected.  Specifically, the ado
  adapter and do postgres subadapter now handle disconnect errors,
  and the postgres adapter handles more types of disconnect errors.
  
* Database#table_exists? now always issues a query to select from the
  table, it no longer attempts to parse the schema to determine the
  information on PostgreSQL and Oracle.

* Date, DateTime, and Time values are now literalized correctly on
  Microsoft Access.

* Connecting with the mysql adapter with an options hash now works if
  the :port option is a string, which makes it easier to use when the
  connection information is stored in YAML.

* The xml_serializer plugin now works around a bug in pure-Java
  nokogiri regarding the handling of nil values.

* Nicer error messages are now used if there is an attempt to call
  an invalid or restricted setter method.

* The RDocs are now formatted with hanna-nouveau, which allows for
  section ordering, so the Database and Dataset RDoc pages are
  more friendly.

= Backwards Compatibility

* If you call a Dataset method such as #each on an eager_graphed
  dataset, you now get plain hashes that have column alias symbol
  keys and their values. Previously, you got a graphed response with
  table alias keys and model values.  It's not wise to depend on the
  behavior, the only supported way of returning records when eager
  loading is to use #all.

* An error is now raised if you attempt to eager load via
  Dataset#eager a many_to_many association that includes an
  :eager_graph option.  Previously, incorrect SQL would have been
  generated and an error raised by the database.
  
* Datasets are no longer guaranteed to have @row_proc,
  @identifier_input_method, and @identifier_output_method defined
  as instance variables.  You should be be using methods to access
  them anyway.

* Database#table_exists? on PostgreSQL no longer accepts an options
  hash.  Previously, you could use a :schema option.  You must now
  provide the schema inside the table argument (e.g. :schema__table).

* If you want to use the rdoc tasks in Sequel's Rakefile, and you are
  still using the hanna RDoc template with RDoc 2.3, you need to
  upgrade to using hanna-nouveau with RDoc 3.8+.

---

### Doc Release Notes 3.27.0 (`doc/release_notes/3.27.0.txt`)

= New Features

* Model.dataset_module has been added for easily adding methods to
  a model's dataset:
  
    Album.dataset_module do
      def with_name_like(x)
        filter(:name.like(x))
      end
      def selling_at_least(x)
        filter{copies_sold > x}
      end
    end
    Album.with_name_like('Foo%').selling_at_least(100000).all
    
  Previously, you could use def_dataset_method to accomplish the
  same thing.  dataset_module is generally cleaner, plus you are
  using actual methods instead of blocks, so calling the methods
  is faster on some ruby implementations.

* Sequel now uses a Sequel::SQLTime class (a subclass of Time) when
  dealing with values for SQL time columns (which don't have a date
  component).  These values are handled correctly when used in
  filters or insert/update statements (using only the time
  component), so Sequel can now successfully round trip values for
  time columns.  Not all adapters support returning time column
  values as SQLTime instances, but the most common ones do.

* You can now drop foreign key, primary key, and unique constraints
  on MySQL by passing the :type=>(:foreign_key|:primary_key|:unique)
  option to Database#drop_constraint.

* The ODBC adapter now has initial support for the DB2 database, use
  the :db_type=>'db2' option to load the support.

= Other Improvements

* The mysql2 adapter now uses native prepared statements.

* The tinytds adapter now uses uses sp_executesql for prepared
  statements.

* DateTime and Time objects are now converted to Date objects when
  they are assigned to a date column in a Model instance.
  
* When converting a Date object to a DateTime object, the resulting
  DateTime object now has no fractional day components.  Previously,
  depending on your timezone settings, it could have had fractional
  day components.

* The mysql2 adapter now supports stored procedures, as long as they
  don't return results.
  
* Mass assignment protection now handles including modules in model
  classes and extending model instances with modules.  Previously, if
  you defined a setter method in a module, access to it may have been
  restricted.
  
* The prepared_statements_safe plugin now works on classes without
  datasets, so you can now do the following to load it for all models:
  
    Sequel::Model.plugin :prepared_statements_safe
    
* Dataset#hash now works correctly when handling SQL::Expression
  instances.
  
* Model#hash now correctly handles classes with no primary key or with
  a composite primary key.
  
* Model#exists? now always returns false for new model objects.

= Backwards Compatibility

* If you were previously setting primary key values manually for new
  model objects and then calling exists? to see if the instance is
  already in the database, you need to change your code from:
  
    model.exists?
    
  to:
  
    model.this.get(1).nil?

---

### Doc Release Notes 3.28.0 (`doc/release_notes/3.28.0.txt`)

= New Adapter Support

* Sequel now has much better support for the DB2 database.

* An ibmdb adapter has been added, and is the recommended adapter to
  to use if you want to connect to DB2 from MRI.

* A jdbc db2 subadapter has been added, allowing good DB2 support on
  JRuby.

* The db2 adapter has been cleaned up substantially, and now works
  well, but it is still recommended that you switch to ibmdb if you
  are using the db2 adapter.

* The firebird adapter has been split into shared and specific parts,
  and quite a few fixes were made to it.

* A jdbc firebird subadapter has been added, allowing connection to
  firebird databases from JRuby.

= New PostgreSQL 9.1 Features

* Dataset#returning has been added for using the RETURNING clause on
  INSERT/UPDATE/DELETE queries.  RETURNING allows such queries to
  return results in much the same way as a SELECT query works.
  When Dataset#returning is used, Dataset #insert, #update, and
  #delete now accept a block that is passed to Dataset #fetch_rows 
  which is yielded plain ruby hashes for each row inserted, updated,
  or deleted.  If Dataset#returning is used and a block is not given
  to those methods, those methods will return an array of plain hashes
  for all rows inserted, updated, and deleted.

* Dataset#with_sql now treats a symbol as a first argument as a method
  name to call to get the SQL.  The expected use case for this is with
  Dataset#returning and insert/update/delete:
    
    DB[:items].
     returning(:id).
     with_sql(:update_sql, :b => :b + 1).
     map(:id)
    
  Basically, it makes it more easily to statically set the
  insert/update/delete SQL, and then be able to use the full
  dataset API for returning results.  As mentioned above, using
  Dataset#returning with #insert, #update, and #delete yields plain
  hashes, so if you want to have the row_proc applied (e.g. you are
  using models), you need to use this method instead, since you can
  then call #each or #all to make sure the row_proc is called on all
  returned rows.

* Dataset#with (common table expressions) now affects
  INSERT/UPDATE/DELETE queries.

* Database#create_table? now uses CREATE TABLE IF NOT EXISTS on
  PostgreSQL 9.1.

= Other New Features

* The :limit option is now respected when eager loading via either
  eager or eager_graph.  By default, Sequel will just do an array
  slice of the resulting ruby array, which gets the correct answer,
  but does not offer any performance improvements.  Sequel also
  offers a new :eager_limit_strategy option for using more advanced
  query types that only load the related records from the database.
  The available values for the :eager_limit_strategy option are:

    :window_function - This uses the row_number window function
      partitioned by the related key fields.  It can only be used
      on databases that support window functions (PostgreSQL 8.4+,
      Microsoft SQL Server 2005+, DB2).
    :correlated_subquery - This uses a correlated subquery that is
      limited.  It works on most databases except MySQL and DB2.

  You can provide a value of true as the option to have Sequel
  pick a strategy to use. Sequel will never use a correlated
  subquery for true, since in some cases it can perform worse than
  loading all related records and doing the array slice in ruby.

  If you want to enable an eager_limit_strategy globally, you can
  set Sequel::Model.default_eager_limit_strategy to a value, and
  all associations that use :limit will default to using that
  strategy.

* one_to_one associations that do not represent true one-to-one
  database relationships, but represent one-to-many relationships
  where you are only returning the first object based on a given
  order are also now handled correctly when eager loading.
  Previously, eager loading such associations resulted in the last
  matching object being associated instead of the first matching
  object being associated.

  You can also use an :eager_limit_strategy for one_to_one
  associations.  In addition to the :window_function and
  :correlated_subquery values, there is also a :distinct_on value
  that is available on PostgreSQL for using DISTINCT ON, which is
  the fastest strategy if you are using PostgreSQL.

* Dataset#map, #to_hash, #select_map, #select_order_map, and
  #select_hash now accept arrays of symbols, and if given arrays
  of symbols, use arrays of results.  For example:

    DB[:items].map([:id, :name])
    # => [[1, 'foo'], [2, 'bar'], ...]
    DB[:items].to_hash([:id, :foo_id], [:name, :bar_id])
    # => {[1, 3]=>['foo', 5], [2, 4]=>['bar', 6], ...}

* For SQL expression objects where Sequel cannot deduce the type
  of the object, it now will consider the type of the argument
  when a &, |, or + operator is used.  For example:

    :x & 1

  Previously, this did "x AND 1", now it does "x & 1".  Using a
  logical operator on an integer doesn't make sense, but it's
  possible people did so if the database uses 1/0 for true/false.
  Likewise:

    :x + 'foo'

  Previously, this did "x + 'foo'" (addition), now it does
  "x || 'foo'" (string concatenation).

* The sql_string, sql_number, and sql_boolean methods are now
  available on SQL::ComplexExpressions, so you can do:

    (:x + 1).sql_string + ' foos'
    # (x + 1) || ' foos'

  Previously, there was not an easy way to generate such SQL
  expressions.

* :after_load association hooks are now applied when using
  eager_graph.  Previously, they were only applied when using
  eager, not when using eager_graph.

* Database#copy_table has been added to the postgres adapter if pg
  is used as the underlying driver.  It allows you to get very
  fast exports of table data in text or CSV format.  It also
  accepts datasets, allowing fast exports of arbitrary queries
  in text or CSV format.

* SQL extract support (:timestamp.extract(:year)) is now emulated
  on the databases that don't natively support it, such as SQLite,
  Microsoft SQL Server, and DB2.  At least the following values are
  supported for extraction: :year, :month, :day, :hour, :minute,
  and :second.

* The bitwise XOR operator is now emulated on SQLite.  Previously,
  attempting to use it would cause the database to raise an error.

* A Database#use_timestamp_timezones accessor has been added on
  SQLite.  This allows you to turn off the use of timezones in
  timestamps by setting the value to false.  This is necessary if you
  want you want to use the SQLite datetime functions, or the new
  ability to emulate extract.
    
  Note that this setting does not affect the current database
  content.  To convert old databases to the new format, you'll
  have to resave all rows that have timestamps.

  At some point in the future, Sequel may default to not using
  timezones in timestamps by default on SQLite, so if you would
  like to rely on the current behavior, you should set this
  accessor to true now.

* Sequel now works around bugs in MySQL when using a subselect with
  a LIMIT by using a nested subselect.

* Sequel now works around issues in Microsoft SQL Server and DB2 when
  using a subselect with IN/NOT IN that uses the emulated offset
  support.

* The jdbc adapter now returns java.sql.Clob objects as
  Sequel::SQL::Blobs.

* Sequel now considers database clob types as the :blob schema type.

* Sequel::SQLTime.create has been added for more easily creating
  instances:

    Sequel::SQLTime.create(hour, minute, second, usec)

* Dataset#select_all now accepts SQL::AliasedExpression and
  SQL::JoinClause arguments and returns the appropriate
  SQL::ColumnAll value that selects all columns from the related
  table.

* Model.set_dataset now accepts Sequel::LiteralString objects that
  represent table names.  This usage is not encouraged except in
  rare cases such as using a set returning function in PostgreSQL.

* Dataset#supports_cte? now takes an optional argument specifying the
  type of query (:insert, :update, :delete, :select).  It defaults to
  :select.

* Dataset#supports_returning? has been added.  It requires an
  argument specifying the type of query (:insert, :update, or
  :delete).

* Dataset#supports_cte_in_subqueries? has been added for checking
  for support for this ability.  Apparently, only PostgreSQL
  currently supports this.  For other adapters that support CTEs but
  not in subqueries, if a subquery with a CTE is used in a JOIN, the
  CTE is moved from the subquery to the main query.

* Dataset#supports_select_all_and_column has been added for seeing
  if "SELECT *, foo ..." style queries are supported.  This is false
  on DB2, which doesn't allow such queries.  When it is false, using
  select_append on a dataset that doesn't specifically select columns
  will now change the query to do "SELECT table.*, foo ..." instead,
  working around the limitation on DB2.

* Dataset#supports_ordered_distinct_on? has been added.  Currently,
  this is only true on PostgreSQL.  MySQL can emulate DISTINCT ON
  using GROUP BY, but it doesn't respect ORDER BY, so it some
  cases it cannot be used equivalently.

* Dataset#supports_where_true? has been added for checking for support
  of WHERE TRUE (or WHERE 1 if 1 is true).  Not all databases support
  using such a construct, and on the databases that do not, you have
  to use WHERE (1 = 1) or something similar.

= Other Improvements

* Sequel 3.27.0 was negatively affected by a serious bug in
  ActiveSupport's Time.=== that has still not been fixed, which
  broke the literalization of Time objects.  In spite of the bad
  precedent it sets, Sequel now avoids using Time.=== on a
  subclass of Time to work around this ActiveSupport bug.

* Dataset#with_pk now uses a qualified primary key instead of an
  unqualified primary key, which means it can now be used correctly
  after joining to a separate table.

* Association after_load hooks when lazy loading are now called
  after the association has been loaded, which allows them to change
  which records are cached.  This makes the lazy load case more
  similar to the eager load case.

* The metaprogrammatically created methods that implement Sequel's
  DSL support have been made significantly faster by using
  module_eval instead of define_method.

* The type translation in the postgres, mysql, and sqlite adapters
  has been made faster by using Method objects that result in more
  direct processing.

* Typecasting values for time columns from Time values to
  Sequel::SQLTime values now correctly handles fractional seconds on
  ruby 1.9.

= Backwards Compatibility

* Dataset#insert_returning_sql has been changed to a private method
  in the PostgreSQL and Firebird adapters, and it operates
  differently than it did previously.  The private
  #insert_returning_pk_sql and #insert_returning_select_sql methods
  have been removed.

* Dataset#with_pk no longer does some defensive checking for misuse of
  primary keys (e.g. providing a composite key when the model uses
  a single key).  Previously, Sequel would raise an Error
  immediately, now such behavior is undefined, with the most likely
  behavior being the database raising an Error.

* The :alias_association_type_map and :alias_association_name_map
  settings have been removed from the :eager_graph dataset option,
  in favor of just storing the related association reflection.

* The internals of the db2 adapter have changed substantially, if you
  were relying on some of the private methods defined in it, you will
  probably have to modify your code.

* The firebird adapter was substantially modified, specifically parts
  related to insert returning autogenerated primary key values, so if
  you were previously using the adapter you should probably take more
  care than usual when testing your upgrade.  

* The Dataset::WITH_SUPPORTED constant has been removed.

* The Dataset#supports_cte? method now accepts an optional argument.
  If you overrode this method, your overridden method now must
  accept an optional argument.

* If you were previously doing:

    :x & 1

  and wanting "x AND 1", you have to switch to:

    :x.sql_boolean & 1

  Likewise, if you were previously doing:

    :x + 'foo'

  and wanting "x + 'foo'", you need to switch to:

    :x.sql_number + 'foo'

* Sequel no longer does defensive type checking in the SQL expression
  support, as it was often more strict than the database and would
  not allow the creation of expressions that were valid for the
  database.

---

### Doc Release Notes 3.29.0 (`doc/release_notes/3.29.0.txt`)

= New Adapter Support

* Sequel now has much better support for Oracle, both in the
  ruby-oci8-based oracle adapter and in the jdbc/oracle adapter.

* Sequel now has much better support for connecting to HSQLDB
  using the jdbc adapter.  This support does not work correctly
  with the jdbc-hsqldb gem, since the version it uses is too
  old.  You'll need to load the .jar file manually until the
  gem is updated.

* Sequel now has much better support for connecting to Apache
  Derby databases using the jdbc adapter.  This works with
  the jdbc-derby gem, but it's recommend you grab an updated
  .jar file as the jdbc-derby gem doesn't currently support
  truncate or booleans.

* The db2 adapter has had most of the remaining issues fixed,
  and can now run Sequel's test suite cleanly.  It's still
  recommended that users switch to the ibmdb adapter if they
  are connecting to DB2.

* A mock adapter has been added which provides a mock Database
  object that allows you to easily set the returned rows, the
  number of rows modified by update/delete, and the
  autogenerating primary key integer for insert.  It also allows
  you to set specific columns in the dataset when retrieving
  rows.  The specs were full of partial implementations of
  mock adapters, this mock adapter is much more complete and
  offers full support for mocking transactions and database
  sharding.  Example:

    DB = Sequel.mock(:fetch=>{:id=>1}, :numrows=>2, :autoid=>3)
    DB[:items].all            # => [{:id => 1}]
    DB[:items].insert         # => 3
    DB[:items].insert         # => 4
    DB[:items].delete         # => 2
    DB[:items].update(:id=>2) # => 2
    DB.sqls # => ['SELECT ...', 'INSERT ...', ...]

  In addition to being useful in the specs, the mock adapter is
  also used if you use bin/sequel without a database argument,
  which makes it much easier to play around with Sequel on the
  command line without being tied to a real database.

= New Transaction Features

* Database after_commit and after_rollback hooks have been added,
  allowing you to set procs that are called after the currently-
  in-effect transaction commits or rolls back.  If the Database
  is not currently in a transaction, the after_commit proc is
  called immediately and the after_rollback proc is ignored.

* Model after_commit, after_rollback, after_destroy_commit, and
  after_destroy_rollback hooks have been added that use the new
  Database after_commit/after_rollback hook to execute code after
  commit or rollback.

* Database#transaction now supports a :rollback => :reraise option
  to reraise any Sequel::Rollback exceptions raised by the block.

* Database#transaction now supports a :rollback => :always option
  to always rollback the transaction, which is mostly useful when
  using transaction-based testing.

* Sequel.transaction has been added, allowing you to run
  simultaneous transactions on multiple Database objects:

    Sequel.transaction([DB1, DB2]){...}
    # similar to:
    DB1.transaction{DB2.transaction{...}}

  You can combine this with the :rollback => :always option to
  easily use multiple databases in the same test suite and make sure
  that changes are rolled back on all of them.

* Database#in_transaction? has been added so that users can detect
  whether the code is currently inside a transaction.

* The generic JDBC transaction support, used by 6 of Sequel's jdbc
  subadapters, now supports savepoints if the underlying JDBC driver
  supports savepoints.

= Other New Features

* A dataset_associations plugin has been added, allowing datasets
  to call association methods, which return datasets of rows in
  the associated table that are associated to rows in the current
  dataset.

    # Dataset of tracks from albums with name < 'M'
    # by artists with name > 'M'

    Artist.filter(:name > 'M').albums.filter(:name < 'M').tracks

    # SELECT * FROM tracks
    # WHERE (tracks.album_id IN (
    #   SELECT albums.id FROM albums
    #   WHERE ((albums.artist_id IN (
    #     SELECT artists.id FROM artists
    #     WHERE (name > 'M')))
    #    AND (name < 'M'))))

* Database#extend_datasets has been added, allowing you to do the
  equivalent of extending all of the database's future datasets
  with a module.  For performance, it creates an anonymous
  subclass of the current dataset class and includes a module in
  it, and uses the subclass to create future datasets.

  Using this feature allows you to override any dataset method
  and call super, similar to how Sequel::Model plugins work. The
  method takes either a module:

    Sequel.extension :columns_introspection
    DB.extend_datasets(Sequel::ColumnsIntrospection)

  or a block that it uses to create an anonymous module:

    DB.extend_datasets do
      # Always select from table.* instead of *
      def from(*tables)
        ds = super
        if !@opts[:select] || @opts[:select].empty?
          ds = ds.select_all(*tables)
        end
        ds
      end
    end

* Database#<< and Dataset#<< now return self, which allow them
  to be used in chaining:

    DB << "UPDATE foo SET bar_id = NULL" << "DROP TABLE bars"
    DB[:foo] << {:bar_id=>0} << DB[:bars].select(:id)

* A Database#timezone accessor has been added, allowing you to
  override Sequel.database_timezone on a per-Database basis, which
  allows you to use two separate Database objects in the same
  process that have different timezones.

* You can now modify the type conversion procs on a per-Database
  basis when using the mysql, sqlite, and ibmdb adapters, by
  modifying the hash returned by Database#conversion_procs.

* Model.dataset_module now accepts a Module instance as an argument,
  and extends the model's dataset with that module.

* When using the postgres adapter with the pg driver, you can now
  use Database#listen to wait for notifications.  All adapters that
  connect to postgres now support Database#notify to send
  notifications:

    # process 1
    DB.listen('foo') do |ev, pid, payload|
      ev # => 'foo'
      notify_pid # => some Integer
      payload # => 'bar'
    end

    # process 2
    DB.notify('foo', :payload=>'bar')

* many_to_one associations now have a :qualify option that can be set
  to false to not qualify the primary key when loading the
  association.  This shouldn't be necessary to use in most cases, but
  in some cases qualifying a primary key breaks certain queries (e.g.
  using JOIN USING on the same column on Oracle).

* Database#schema can now take a dataset as an argument if it just
  selects from a single table.  If a dataset is provided, the
  schema parsing will use that dataset's identifier_input_method
  and identifier_output_method for the parsing, instead of the
  database's default.  This makes it possible for Model classes
  to correctly get the table schema if they use a dataset whose
  identifier_(input|output)_method differs from the database
  default.

* On databases that support common table expressions (CTEs) but do
  not support CTE usage in subselects, Sequel now emulates support
  by moving CTEs from the subselect to the main select when using
  the Dataset from, from_self, with, with_recursive, union,
  intersect, and except methods.

* The bitwise compliment operator is now emulated on H2.

* You can now set the convert_tinyint_to_bool setting on a
  per-Database basis in the mysql and mysql2 adapters.

* You can now set the convert_invalid_date_time setting on a
  per-Database basis in the mysql adapter.

* Database instances now have a dataset_class accessor that allows
  you to set which class is used when creating datasets.  This is
  mostly used to implement the extend_datasets support, but it
  could be useful for other purposes.

* Dataset#unused_table_alias now accepts an optional 2nd argument,
  which should be an array of additional symbols that should be
  considered as already used.

* Dataset#requires_placeholder_type_specifiers? has been added to
  check if the dataset requires you use type specifiers for
  bound variable placeholders.

  The prepared_statements plugin now checks this setting and works
  correctly on adapters that set it to true, such as oracle.

* Dataset#recursive_cte_requires_column_aliases? has been added
  to check if you must provide a column list for a recursive CTE.

  The rcte_tree plugin now checks this setting an works correctly
  on databases that set it to true, such as Oracle and HSQLDB.

= Performance Improvements

* Numerous optimizations were made to loading model objects from
  the database, resulting in a 7-16% speedup.

  Model.call was added, and now .load is just an alias for .call.
  This allows you to make the model dataset's row_proc the model
  itself, instead of needing a separate block, which improves
  performance.

  While Model.load used to call .new (and therefore #initialize),
  Model.call uses .allocate/#set_values/#after_initialize for speed.
  This saves a method call or two, and skips setting the @new
  instance variable.

* Dataset#map, #to_hash, #select_map, #select_order_map, and
  #select_hash are now faster if any of the provided arguments are
  an array of symbols.

* The Model.[] optimization is now applied in more cases.

= Other Improvements

* Sequel now creates accessor methods for all columns in a model's
  table, even if the dataset doesn't select the columns.  This has
  been the specified behavior for a while, but the spec was broken.
  This allows you do to:

    Model.dataset = DB[:table].select(:column1, :column2)
    Model.select_more(:column3).first.column3

* Model.def_dataset_method now correctly handles method names that
  can't be used directly (such as method names with spaces).  This
  isn't so the method can be used with arbitrary user input, but
  it will allow safe creation of dataset methods that are derived
  from column names, which could contain spaces.

* Model.def_dataset_method no longer overrides private model
  methods.

* The optimization that Model.[] uses now works correctly if the
  model's dataset uses a different identifier_input_method than
  the database.

* Sharding is supported correctly by default for the transactions
  used by model objects.  Previously, you had to use the sharding
  plugin to make sure the same shard was used for transactions as
  for the insert/update/delete statements.

* Sequel now fully supports using an aliased table for the
  :join_table option of a many_to_many association.  The only real
  use case for an aliased :join_table option is when the join table
  is the same as the associated model table.

* A bug when eagerly loading a many_through_many association with
  composite keys where one of the join tables requires an alias
  has been fixed.

* Sequel's transaction internals have had substantial improvements.
  You can now open up simultaneous transactions on two separate
  shards of the same Database object in the same thread.  The new
  design allows for future support of connection pools that aren't
  based on threads.  Sequel no longer abuses thread-local variables
  to store savepoint state.

* Dataset#select_map and #select_order_map now return an array of
  single element arrays if given an array with a single entry as
  an argument.  Previously, they returned an array of values, which
  wasn't consistent.

* Sequel's emulation of bitwise operators with more than 2 arguments
  now works on all adapters that use the emulation.  The emulation
  was broken in 3.28.0 when more than 2 arguments were used on H2,
  DB2, Microsoft SQL Server, PostgreSQL, and SQLite.

* Dataset#columns now correctly handles the emulated offset support
  used on DB2, Oracle, and Microsoft SQL Server when using the
  jdbc, odbc, ado, and dbi adapters.  Previously, Dataset#columns
  could contain the row number column, which wasn't in the
  hashes yielded by Dataset#each.

* Sequel can now parse primary key information on Microsoft SQL
  Server.  Previously, the only adapter that supported this was the
  jdbc adapter, which uses the generic JDBC support.  The shared
  mssql adapter now supports parsing the information directly from
  the database system tables.  This means that if you are using
  Model objects with a Microsoft SQL Server database using the
  tinytds, odbc, or ado adapters, the model primary key
  information will be set automatically.

* Sequel's prepared statement support no longer defines singleton
  methods on the prepared statement objects.

* StringMethods#like is now case sensitive on SQLite and Microsoft
  SQL Server, making it more similar to other databases.

* Sequel now works around an SQLite column naming bug if you select
  columns qualified with the alias of a subselect without providing
  an alias for the column itself.

* Sequel now handles more bound variable types when using bound
  variables outside of prepared statements on SQLite.

* Sequel now works around a bug in certain versions of the
  JDBC/SQLite driver when emulating alter table support for
  operations such as drop_column.

* Sequel now emulates the add_constraint and drop_constraint
  alter table operations on SQLite, though the emulation has
  issues.

* Sequel now correctly handles composite primary keys when
  emulating alter_table operations on SQLite.

* Sequel now applies the correct PRAGMA statements by default when
  connecting to SQLite via the amalgalite and swift adapters.

* Sequel now supports using savepoints inside prepared transactions
  on MySQL.

* Sequel now closes JDBC ResultSet objects as soon as it is done
  using them, leading to potentially lower memory usage in the JDBC
  adapter, and fixes issues if you try to drop a table before
  GC has collected a related ResultSet.

* Sequel can now correctly insert all default values into a table
  on DB2.  Before, this didn't work correctly if the table had more
  than one column.

* Another type of disconnection error is now recognized in the
  mysql2 adapter.

* Sequel now uses better error messages if you attempt to execute a
  prepared statement without a name using the postgres, mysql, and
  mysql2 adapters.

* Some small fixes have been made that allow Sequel to run better
  when $SAFE=1.  However, Sequel is not officially supported using
  $SAFE > 0, so there could be many issues remaining.

* Sequel's core and model specs were cleaned up by using the mock
  adapter to eliminate a lot of redundant code.

* Sequel's integration tests were sped up considerably, halving
  the execution time on some adapters.

= Backwards Compatibility

* Because Model.load is now an alias for .call, plugins should no
  longer override load.  Instead, they should override .call.

* Loading model objects from the database no longer calls
  Model#initialize.  Instead, it calls Model.allocate,
  Model#set_values, and Model#after_initialize.  So if you were
  overriding #initialize and expecting the changes to affect model
  objects loaded from the database, you need to change your code.

  Additionally, @new is no longer set to false for objects retrieved
  from the database, since setting it to false hurts performance.
  Model#new? still returns true or false, so this only affects you
  if you are checking the instance variables directly.

* Dataset#<< no longer returns the autogenerated primary key for the
  inserted row.  As mentioned above, it now returns self to allow for
  chaining.  If you were previously relying on the return value,
  switch from #<< to #insert.

* Dataset#map no longer calls the row_proc if given an argument, and
  Dataset#to_hash no longer calls the row_proc if given two arguments.
  This should only affect your code if you were using a row_proc that
  modified the content of the hash (e.g. Model#after_initialize). If
  you were relying on the old behavior, switch:

    dataset.map(:foo)
    # to
    dataset.map{|r| r[:foo]}

    dataset.to_hash(:foo, :bar)
    # to
    h = {}
    dataset.each{|r| h[r[:foo]] = r[:bar]}
    h

* Model classes now need to have a dataset before you can define
  associations on them.

* Model classes now pass their dataset to Database#schema, instead of
  their table name.

* The :eager_block association option (which defaults to the
  association's block argument) is now called before the :eager_graph
  association option has been applied, instead of after.

* The many_to_many association reflection :qualified_right_key entry
  is now a method named qualified_right_key.  Switch any
  code using association_reflection[:qualified_right_key] to use
  association_reflection.qualified_right_key.

* If you are using like on SQLite and Microsoft SQL Server and want
  it to be case insensitive, switch to using ilike:

    # Case sensitive
    DB[:foos].where(:name.like('bar%'))
    # Case insensitive
    DB[:foos].where(:name.ilike('bar%'))    

  Sequel now sets the case_sensitive_like PRAGMA to true by default
  on SQLite.  To set it to false instead, pass the
  :case_sensitive_like=>false option to the database when creating it.

* Sequel's alter table emulation on SQLite now renames the current
  table then populates the replacement table, instead of
  populating the replacement table at a temporary name, dropping
  the current table, and then renaming the replacement table.

* The strings 'n' and 'no' (case insensitive) when typecasted to
  boolean are now considered false values instead of true.

* The transaction internals had extensive changes, if you have any
  code that depended on the transaction internals, it will probably
  require changes.

* Using the Sequel::MySQL module settings for convert_tinyint_to_bool
  and convert_invalid_date_time now only affects future Database
  objects.  You should switch to using the per-Database methods
  if you are currently using the Sequel::MySQL module methods.

* The customized transaction support in the do (DataObjects) adapter
  was removed.  All three subadapters (postgres, mysql, sqlite) of
  the do adapter implement their own transaction support, so this
  should have no effect unless you were using the do adapter with
  a different database type.

* The oracle support changed dramatically, so if you were relying
  on the internals of the oracle support, you should take extra
  care when upgrading.

= Advance Notice

* The next release of Sequel will contain significant changes to
  how a dataset is literalized into an SQL string.  If you have
  a custom plugin, extension, or adapter that overrides a
  method containing "literal", "sql", or "quote", or you make
  other modifications or extensions to how Sequel currently
  literalizes datasets to SQL, your code will likely need to
  be modified to support the next release.

---

### Doc Release Notes 3.3.0 (`doc/release_notes/3.3.0.txt`)

New Features
------------

* An association_proxies plugin has been added.  This is not a
  full-blown proxy implementation, but it allows you to write code
  such as:
  
    artist.albums.filter{num_tracks > 10}
    
  Without the plugin, you have to call filter specifically on the
  association's dataset:
  
    artist.albums_dataset.filter{num_tracks > 10}

  The plugin works by proxying array methods to the array of
  associated objects, and all other methods to the association's
  dataset.  This results in the following behavior:
  
    # Will load the associated objects (unless they are already
    # cached), and return the length of the array
    artist.albums.length
    
    # Will issue an SQL query with COUNT (even if the association
    # is already cached), and return the result
    artist.albums.count

* The add_*/remove_*/remove_all_* association methods now take
  additional arguments that are passed down to the
  _add_*/_remove_*/_remove_all_* methods.  One of the things this
  allows you to do is update additional columns in join tables for
  many_to_many associations:

    class Album
      many_to_many :artists
      def _add_artist(artist, values={})
        DB[:albums_artists].
          insert(values.merge(:album_id=>id,
                              :artist_id=>artist.id))
      end
    end
    
    album = Album[1]
    artist1 = Artist[2]
    artist2 = Artist[3]
    album.add_artist(artist1, :relationship=>'composer')
    album.add_artist(artist2, :relationship=>'arranger')

* The JDBC adapter now accepts a :convert_types option to turn off
  Java type conversion.  The option is true by default for
  backwards compatibility and correctness, but can be set to false
  to double performance.  The option can be set at the database
  and dataset levels:

    DB = Sequel.jdbc('jdbc:postgresql://host/database',
                     :convert_types=>false)
    DB.convert_types = true
    ds = DB[:table]
    ds.convert_types = false

* Dataset#from_self now takes an option hash and respects an
  :alias option, giving the table alias to use.

* Dataset#unlimited was added, similar to unfiltered and unordered.

* SQL::WindowFunction is now a subclass of SQL::GenericExpression,
  so you can alias it and treat it like any other SQL::Function.

Other Improvements
------------------

* Microsoft SQL Server support is much, much better in Sequel 3.3.0
  than in previous versions.  Support is pretty good with the ODBC,
  ADO, and JDBC adapters, close to the level of support for
  PostreSQL, MySQL, SQLite, and H2.  Improvements are too numerous
  to list, but here are some highlights:
  
  * Dataset#insert now returns the primary key (identity field), so
    it can be used easier with models.
    
  * Transactions can now use savepoints (except on ADO).
  
  * Offsets are supported when using SQL Server 2005 or 2008, using
    a ROW_NUMBER window function.  However, you must specify an
    order for your dataset (which you probably are already doing if
    you are using offsets).

  * Schema parsing has been implemented, though it doesn't support
    primary key parsing (except on JDBC, since the JDBC support is
    used there).
  
  * The SQL syntax Sequel uses is now much more compatible, and
    most schema modification methods and database types now work
    correctly.

* The ADO and ODBC adapters both work much better now.  The ADO
  adapter no longer attempts to use transactions, since I've found
  that ADO does not give a stable native connection (and hence
  transactions weren't possible).  I strongly recommend against
  using the ADO adapter in production.

* The H2 JDBC subadapter now supports rename_column, set_column_null,
  set_column_type, and add_foreign_key.

* Altering a columns type, null status, or default is now supported
  on SQLite.  You can also add primary keys and unique columns.

* Both the ADO and ODBC adapters now catch the native exception
  classes and raise Sequel::DatabaseErrors.

* Model classes now default to associating to other classes in the
  same scope.  This makes it easier to use namespaced models.

* The schema parser and schema dumper now support the following
  types: nchar, nvarchar, ntext, smalldatetime, smallmoney, binary,
  and varbinary.

* You can now specify the null status for a column using :allow_null
  in addition to :null.  This is to make it easier to use the
  table creation methods with the results of the schema parser.

* Renaming a NOT NULL column without a default now works on MySQL.

* Model class initialization now raises an exception if there is a
  problem connecting to the database.
  
* Connection pool performance has been increased slightly.

* The literal_time method in the ODBC adapter has been fixed.

* An unlikely but potential bug in the MySQL adapter has been fixed.

Backwards Compatibility
-----------------------

* The convert_tinyint_to_bool setting moved from the main Sequel
  module to the Sequel::MySQL module.  The native MySQL adapter is
  the only adapter that converted tinyint columns to booleans when
  the rows are returned, so you can only use the setting with the
  native MySQL adapter.
  
  Additionally, the setting's behavior has changed.  When parsing
  the schema, now only tinyint(1) columns are now considered as
  boolean, instead of all tinyint columns. This allows you to use
  tinyint(4) columns for storing small integers and tinyint(1)
  columns as booleans, and not have the schema parsing support
  consider the tinyint(4) columns as booleans.  Unfortunately,
  due to limitations in the native MySQL driver, all tinyint
  column values are converted to booleans upon retrieval, not just
  tinyint(1) column values.
  
  Unfortunately, the previous Sequel behavior was to use the
  default tinyint size (tinyint(4)) when creating boolean columns
  (using the TrueClass or FalseClass generic types).  If you were
  using the generic type support to create the columns, you should
  modify your database to change the column type from tinyint(4) to
  tinyint(1).
  
  If you use MySQL with tinyint columns, these changes have the
  potential to break applications.  Care should be taken when
  upgrading if these changes apply to you.

* Model classes now default to associating to other classes in the
  same scope.  It's highly unlikely anyone was relying on the
  previous behavior, but if you have a model inside a module that
  you are associating to a model outside of a module, you now need
  to specify the associated class using the :class option. 
  
* Model#save no longer includes the primary key fields in the SET
  clause of the UPDATE query, only in the WHERE clause.  I'm not
  sure if this affects backwards compatibility of production code,
  but it can break tests that expect specific SQL.

* Behavior to handle empty identifiers has now been standardized.
  If any database adapter returns an empty identifier, Sequel will
  use 'untitled' as the identifier.  This can break backwards
  compatibility if the adapter previously used another default and
  you were relying on that default.  This was necessary to fix any
  possible "interning empty string" exceptions.

* On MSSQL, Sequel now uses the datetime type instead of the
  timestamp type for generic DateTimes.  It now uses bit for the
  TrueClass and FalseClass generic types, and image for the File
  generic type.

* Sequel now unescapes URL parts:

    Sequel.connect(ado:///db?host=server%5cinstance)

  However, this can break backward compatibility if you previously
  expected it not to be unescaped.

* The columns_for private SQLite Database method has been removed.

---

### Doc Release Notes 3.30.0 (`doc/release_notes/3.30.0.txt`)

= Dataset Literalization Refactoring

* As warned about in the 3.29.0 release notes, dataset literalization
  has been completely refactored.  It now uses an append-only design
  which is faster in all cases, about twice as fast for large objects
  and deeply nested structures, and over two orders of magnitude
  faster in some pathological cases.

  This change should not affect applications, but may affect custom
  extensions or adapters that dealt with literalization of objects.
  Most literalization methods now have a method with an _append
  suffix that does the actual literalization, which takes the sql
  string to append to as the first argument.  If you were overriding
  a literalization method, you now probably need to override the
  _append version instead.  If you have this literalization method:

    def foo_sql(bar)
      "BAR #{literal(bar.baz)}"
    end

   You need to change the code to:

    def foo_sql_append(sql, bar)
      sql << "BAR "
      literal_append(sql, bar.baz)
    end

    def foo_sql(bar)
      sql = ""
      foo_sql_append(sql, bar)
      sql
    end

  If you have questions about modifying your custom adapter or
  extension, please ask on the Google Group or the IRC channel.

= New Features

* Model#set_server has been added to the base support (it was
  previously only in the sharding plugin), which allows you to
  set the shard on which to save/delete the model instance:

    foo1.set_server(:server_a).save
    foo2.set_server(:server_a).destroy

* Model#save now accepts a :server option that uses set_server
  to set the shard to use.  Unlike most other #save options, this
  option persists past the end of the save.  Previously, the
  :server option only affected the transaction code, it now
  affects the INSERT/UPDATE statement as well.

* When initiating a new dataset graph, any existing selected
  columns is assumed to be the columns to select for the graph from
  the current/master table.  Before, there was not a way to specify
  the columns to select from the current/master table.

* A :graph_alias_base association option has been added, which is
  used to set the base alias name to use when eager graphing.  This
  is mostly useful when cascading eager graphs to dependent
  associations, where multiple associations with the same name in
  different models are being graphed simultaneously.

* You can now specify nanoseconds and a timezone offset
  when converting a hash or array to a timestamp.  The nanoseconds
  and offset are the 7th and 8th entries in the array, and the :nanos
  and :offset entry in the hash.

* The postgres adapter now respects a :connect_timeout option if you
  are using the pg driver.

= Other Improvements

* Type conversion of Java to Ruby types in the JDBC adapter has been
  made much faster, as conversion method lookup is now
  O(number of columns) instead of
  O(number of columns*number of rows).

* Sequel::SQL::Blob literalization is now much faster on adapters that
  use hex encoding, by switching to String#unpack('H*').

* Database#after_commit and after_rollback now respect the :server
  option to set the server/shard to use.

* Symbol splitting (e.g. for table__column) is now slightly faster.

* All adapters now pass the dataset :limit/:offset value through
  Dataset#literal instead of using it verbatim.  Note that
  Dataset#limit already called to_i on input strings, so this isn't
  a security issue.  However, the previous code broke if you
  provided a Sequel-specific object (e.g. Sequel::SQL::Function) as
  the :limit/:offset value.

* Calling graph and eager_graph on an already graphed dataset no
  longer modifies the receiver.

* Model#set_server now correctly handles the case where @this is
  already loaded.

* Dataset#destroy for model datasets now uses the dataset's shard
  for transactions.

* When emulating offset support using ROW_NUMBER (on Microsoft SQL
  Server, DB2, and Oracle), explicitly order by the ROW_NUMBER
  result, as otherwise the results are not guaranteed to be ordered.

* Explicitly force a case insensitive collation when emulating ILIKE
  on Microsoft SQL Server.  Previously, ILIKE could be case sensitive
  on Microsoft SQL Server if case sensitive collation was the
  database default.

* Using on_duplicate_key_update with prepared statements on MySQL now
  works correctly.

* The tinytds adapter now works correctly if the
  identifier_output_method is nil.

* The plugin/extension specs were cleaned up using the mock adapter.

= Backwards Compatibility

* In addition to the previously mentioned dataset literalization
  changes, any custom adapters that overrode *_clause_methods
  methods need to be modified to add a method that adds the
  SELECT/UPDATE/INSERT/DELETE.  Previously, this was done by default,
  but due to common table expressions and the dataset literalization
  changes, a separate method is now needed.

* Dataset#on_duplicate_key_update_sql has been removed from the shared
  mysql adapter.

* The :columns dataset option used when inserting is no longer
  literalized in advance.

* Dataset#as_sql no longer takes an expression, it just takes the
  alias, and only adds the alias part.

---

### Doc Release Notes 3.31.0 (`doc/release_notes/3.31.0.txt`)

= New Features

* The serialization plugin can now support custom serialization
  formats, by supplying a serializer/deserializer pair of
  callable objects.  You can also register custom deserializers
  via Sequel::Plugins::Serialization.register_format, so that
  they can be referenced by name.  Example:
  
    Sequel::Plugins::Serialization.register_format(:reverse,
      lambda{|v| v.reverse},
      lambda{|v| v.reverse})
    class User < Sequel::Model
      serialize_attributes :reverse, :password
    end

* Dataset#import and #multi_insert now support a
  :return=>:primary_key option.  When this option is used, the
  methods return an array of primary key values, one for each
  inserted row.  Usage of this option on MySQL requires that a
  separate query be issued per row (instead of the single
  query for all rows that MySQL would usually use).
  
* PostgreSQL can now use Dataset#returning in conjunction with
  import/multi_insert to set a custom column to return.
  
* Microsoft SQL Server can now use Dataset#output in conjunction with
  import/multi_insert to set a custom column to return.
  
* Dataset#import and #multi_insert now respect a :server option to
  set the server/shard on which to execute the queries.
  Additionally, options given to this method are also passed to
  Dataset#transaction.

* Dataset#insert_multiple now returns an array of inserted primary
  keys.

* Model.def_column_alias has been added to make it easy to create
  alias methods for columns.  This is useful if you have a legacy
  database and want to create friendly method names for the
  underlying columns.  Note that this alias only affects the setter
  and getter methods.  This does not affect the dataset level, so you
  still need to use the actual column names in dataset filters.

* many_to_one associations can now have the same name as the related
  foreign key column, using the :key_column option.  Use of this
  feature is not recommended, as it is much better to either rename
  the column or rename the association.  Here's an example of usage:
  
    # Example schema:
    #  albums           artists
    #   :id        /-->  :id
    #   :artist --/      :name
    #   :name
    class Album < Sequel::Model
      def_column_alias(:artist_id, :artist)
      many_to_one :artist, :key_column=>:artist
    end

* The mock adapter can now mock out database types, by providing a
  shared adapter name as the host (e.g. mock://postgres).  This
  emulation is not perfect, but in most cases it allows you to see
  what SQL Sequel would generate on a given database without needing
  to install the required database driver.

* Sequel now supports creating full text indexes on Microsoft SQL
  Server.  Before using it, you must have previously setup a default
  full text search catalog, and you need to provide a :key_index
  option with an index name symbol.
  
* Dataset#group_rollup and #group_cube methods have been added for
  GROUP BY ROLLUP and GROUP BY CUBE support.  These features are in
  a recent SQL standard, and they are supported to various degrees on
  Microsoft SQL Server, DB2, Oracle, MySQL, and Derby.

* Dataset#full_text_search on Microsoft SQL Server now supports
  multiple search terms.
  
* The jdbc adapter now supports a :login_timeout option, giving the
  timeout in seconds.

= Other Improvements

* Dataset#exists can now be used with prepared statement
  placeholders.

* Dataset#full_text_search can now be used with prepared statement
  placeholders on PostgreSQL, MySQL, and Microsoft SQL Server.
  
* If tables from two separate schema are detected when parsing the
  schema for a table on PostgreSQL, an error is now raised.
  Previously, no error was raised, which led to weird errors later,
  such as duplicate columns in a model's primary_key.

* RETURNING is now supported with UPDATE/DELETE on PostgreSQL 8.2+.
  Previously, Sequel only supported it on 9.1+, but PostgreSQL
  introduced support for it in 8.2.

* The shared postgres adapter now correctly handles the return value
  for Dataset#insert if you provide a separate column array and value
  array on PostgreSQL < 8.2.
  
* Handle case in the PostgreSQL adapter where the server version
  cannot be determined via a query.
  
* H2 clob types are now treated as string instead of as blob.
  Treating clob as blob breaks on H2, as it doesn't automatically
  hex-unescape the input for clobs as it does for blobs.
  
* Dataset#empty? now works correctly when the dataset has an offset
  and offset support is being emulated.

* The mock adapter no longer defaults to downcasing identifiers on
  output.

= Backwards Compatibility

* Dataset#exists now returns a PlaceholderLiteralString instead of a
  LiteralString, which could potentially break some code.  If you
  would like a String returned, you can pass the returned object to
  Dataset#literal:
  
    dataset.literal(dataset.exists)

* Dataset#from no longer handles :a__b__c___d as "a.b.c AS d".  This
  was not the intended behavior, and nowhere else in Sequel is a
  symbol treated that way.  Now, Dataset#from is consistent with the
  rest of Sequel, using "a.b__c AS d".  This should only affect
  people in very rare cases, as most databases don't use three level
  qualified tables.  One exception is Microsoft SQL Server, which can
  use three level qualified tables for cross-database access.
  
* Previously, Dataset#insert_multiple returned an array of hashes, now
  it returns an array of primary key values.

* Dataset#EXRACT_CLOSE in the shared sqlite adapter has been renamed to
  Dataset#EXTRACT_CLOSE.
  
* Dataset::StoredProcedureMethods::SQL_QUERY_TYPE and
  Dataset::ArgumentMapper::SQL_QUERY_TYPE constants have been removed,
  as have related sql_query_type private methods.

* The serialization plugin was significantly refactored.
  Model.serialization_map now contains a callable object instead of a
  Symbol, and Model.serialization_format has been removed.
  Model.define_serialized_attribute_accessors private method now takes
  two callable objects before the columns, instead of a single symbol.

---

### Doc Release Notes 3.32.0 (`doc/release_notes/3.32.0.txt`)

= New Features

* Prepared statements now support :map and :to_hash prepared
  statement types.  The main reason for this is that certain
  extensions (e.g. sequel_pg) optimize map/to_hash calls, and
  there previously was not a way to use prepared statements
  with the map/to_hash optimizations.

* Sequel.empty_array_handle_nulls has been added to change how
  IN/NOT IN operations with an empty array are handled.  See
  the Backwards Compatibility section for details.

* 5 new association options have been added that allow you to
  define associations where the underlying columns clash with
  standard ruby method names:

    many_to_one :primary_key_method
    one_to_many :key_method
    one_to_many :primary_key_column
    many_to_many :left_primary_key_column
    many_to_many :right_primary_key_method

  Using these new options, you can now define associations
  that work correctly when the underlying primary/foreign key
  columns clash with existing ruby method names.  See the RDoc
  for details.

* A use_after_commit_rollback setting has been added to models.
  This defaults to true, but can be set to false for performance
  or to allow models to be used in prepared transactions
  (which don't support after_commit/after_rollback).

* Dataset#update_ignore has been added when connecting to MySQL,
  enabling use of the UPDATE IGNORE syntax to skip updating a row
  if the update would cause a unique constraint to be violated.

* Database#indexes is now supported when connecting to Microsoft
  SQL Server.

* On Microsoft SQL Server, the :include option is now supported
  when creating indexes, for storing column values in the index,
  which can be used by the query optimizer.

= Other Improvements

* The filtering/excluding by associations code now uses qualified
  identifiers instead of unqualified identifiers, which allows it
  to avoid ambiguous column names if you are doing your own joins.

* Virtual row blocks that return arrays are now handled correctly
  in Dataset#select_map/select_order_map.

* Dataset#select_map/select_order_map can now take both a block
  argument as well as a regular argument.

* Dataset#select_order_map now handles virtual row blocks that
  return ordered expressions.

* Database#table_exists? should no longer generate false negatives
  if you only have permission to retrieve some column values but
  not all.  Note that if you lack permission to SELECT from the
  table itself, table_exists? can still generate false negatives.

* The active_model plugin now supports ActiveModel 3.2, by adding
  support for to_partial_path.

* The serialization_modification_detection plugin now handles
  changed_columns correctly both for new objects and after saving
  objects.

* The serialization plugin now clears the deserialized values when
  it does the automatic refresh after saving a new object, mostly for
  consistency.  You can use the skip_create_refresh plugin to skip
  refreshing when creating a new model object.

* Column default values are now wrapped in parentheses on SQLite,
  which fixes some cases such as when the default is an SQL function
  call.

* Alter table emulation now works correctly on SQLite when foreign
  keys reference the table being altered.  The emulation requires
  a renaming/deleting the existing table and creating a new table,
  which can break foreign key references.  Sequel now disables the
  foreign key PRAGMA when altering tables, so SQLite won't track
  the table renames and break the foreign key relationships.

* The set_column_type table alteration method no longer modifies
  default values and NULL/NOT NULL settings on Microsoft SQL
  Server, H2, and SQLite.

* On MySQL, Time/DateTime columns now use the timestamp type if the
  default value is Sequel::CURRENT_TIMESTAMP, since it is currently
  impossible for MySQL to have a non-constant default for a
  datetime column (without using a workaround like a trigger).

* Metadata methods such as tables, views, and view_exists? are now
  handled correctly on Oracle if custom identifier input methods
  are used.

* Sequel now ignores errors that occur when attempting to get
  information on column defaults in Oracle (which can happen if you
  lack permission to the appropriate table).  Previously, such errors
  would cause the schema parser to raise an error, now, the schema
  information is just returned without default information.

* Database#indexes now skips the primary key index when connecting to
  DB2, Derby, HSQLDB, and Oracle via the jdbc adapter.

* Database#indexes now works correctly on DB2.

* The progress adapter has been fixed, it had been broken since the
  dataset literalization refactoring.

* Dataset#naked! now works correctly.  Previously, it just returned
  the receiver unmodified.

* Dataset#paginate! has been removed, as it was broken.

* The query extension no longer breaks Dataset#clone if an argument
  is not given.

* Transaction related queries are no longer logged twice in the mock
  adapter.

= Backwards Compatibility

* Sequel's default handling of NOT IN operators with an empty array
  of values has changed, which can change which rows are returned for
  such queries.
 
  Previously, Sequel was inconsistent in that it tried to handle NULL
  values correctly in the IN case, but not in the NOT IN case.  Now,
  it defaults to handling NULL values correctly in both cases:

    # 3.31.0
    DB[:a].where(:b=>[])
    # SELECT * FROM a WHERE (b != b)
    DB[:a].exclude(:b=>[])
    # SELECT * FROM a WHERE (1 = 1)

    # 3.32.0
    DB[:a].where(:b=>[])
    # SELECT * FROM a WHERE (b != b)
    DB[:a].exclude(:b=>[])
    # SELECT * FROM a WHERE (b = b)

  The important change in behavior is that in the NOT IN case, if
  the left hand argument is NULL, the filter returns NULL instead
  of true.  This has the potential to change query results.

  "Correct" here is really an opinion and not a fact, as there are
  valid arguments for the alternative behavior:

    DB[:a].where(:b=>[])
    # SELECT * FROM a WHERE (1 = 0)
    DB[:a].exclude(:b=>[])
    # SELECT * FROM a WHERE (1 = 1)

  The difference is that the "correct" NULL behavior is more
  consistent with the non-empty array cases.  For example, if b is
  NULL:

    # "Correct" NULL handling
    #  Empty array: where(:b=>[])
    WHERE (b != b) # NULL
    WHERE (b = b) # NULL
    #  Non-empty array: where(:b=>[1, 2])
    WHERE (b IN (1, 2)) # NULL
    WHERE (b NOT IN (1, 2)) # NULL

    # Static boolean handling
    #  Empty array: where(:b=>[])
    WHERE (1 = 0) # false
    WHERE (1 = 1) # true
    #  Non-empty array: where(:b=>[1, 2])
    WHERE (b IN (1, 2)) # NULL
    WHERE (b NOT IN (1, 2)) # NULL

  Sequel chooses to default to behavior consistent with the non-empty
  array cases (similar to SQLAlchemy).  However, there are two
  downsides to this handling.  The first is that some databases with
  poor optimizers (e.g. MySQL) might do a full table scan with the
  default syntax.  The second is that the static boolean handling may
  be generally preferable, if you believe that IN/NOT IN with an
  empty array should always be true or false and never NULL even if
  the left hand argument is NULL.

  As there really isn't a truly correct answer in this case, Sequel
  defaults to the "correct" NULL handling, and allows you to switch
  to the static boolean handling via:

    Sequel.empty_array_handle_nulls = false

  This is currently a global setting, it may be made Database or
  Dataset specific later if requested.  Also, it is possible the
  default will switch in the future, so if you care about a specific
  handling, you should set your own default.

* Database#table_exists? now only rescues Sequel::DatabaseErrors
  instead of StandardErrors, so it's possible it will raise errors
  instead of returning false on custom adapters that don't wrap
  their errors correctly.

---

### Doc Release Notes 3.33.0 (`doc/release_notes/3.33.0.txt`)

= New Features

* A server_block extension has been added that makes Sequel's
  sharding support easier to use by scoping database access inside
  the block to a given server/shard:

    Sequel.extension :server_block
    DB.extend Sequel::ServerBlock
    DB.with_server(:shard_1) do
      # All of these will execute against shard_1
      DB.tables
      DB[:table].all
      DB.run 'SOME SQL'
    end

* An arbitrary_servers extension has been added that extends
  Sequel's sharding support so that you can use arbitrary
  connection options instead of referencing an existing, predefined
  server/shard:

    Sequel.extension :arbitrary_servers
    DB.pool.extend Sequel::ArbitraryServers
    DB[:table].server(:host=>'foo', :database=>'bar').all

  You can use this extension in conjunction with the server_block
  extension:

    DB.with_server(:host=>'foo', :database=>'bar') do
      DB.synchronize do
        # All of these will execute on host foo, database bar
        DB.tables
        DB[:table].all
        DB.run 'SOME SQL'
      end
    end

  The combination of these two extensions makes it pretty easy to
  write a thread-safe Rack middleware that scopes each request
  to an arbitrary database.

* The sqlite adapter now supports an integer_booleans setting
  for using 1/0 for true/false values, instead of the the 't'/'f'
  values used by default.  As SQLite recommends using integers to
  store booleans, converting your existing database and enabling
  this setting is recommended, but for backwards compatibility it
  is set to false.  You can convert you existing database by doing
  the following for each table/column that has booleans:

    DB[:table].update(:boolean_column=>{'t'=>1}.
                        case(0, :boolean_column))

  The integer_booleans default setting may change in a future
  version of Sequel, so you should set it manually to false if you
  prefer the current default.

* You can now disable transaction use in migrations, in one of two
  ways.  You generally only need to do this if you are using an
  SQL query inside a migration that is specifically not supported
  inside a transaction, such as CREATE INDEX CONCURRENTLY on
  PostgreSQL.
  
  The first way to disable transactions is on a per-migration basis
  by calling the no_transaction method inside the Sequel.migration
  block:

    Sequel.migration do
      no_transaction
      change do
        # ...
      end
    end

  That will make it so that a transaction is not used for that
  particular migration.  The second way is passing the
  :use_transactions=>false option when calling Migrator.run (using
  the API), which will completely disable transactions for all
  migrations during the migrator run.

* The postgres adapter now respects an :sslmode option when using
  pg as the underlying driver, you can set the value of this option to
  disable, allow, prefer, or require.

* Database#create_schema and #drop_schema are now defined when
  connecting to PostgreSQL.

* Database#supports_savepoints_in_prepared_transactions? has been
  added for checking if savepoints are supported inside prepared
  transactions.  This is true if both savepoints and prepared
  transactions are both supported, except on MySQL > 5.5.12 (due to
  MySQL bug 64374).

= Other Improvements

* The mysql and mysql2 adapters now both provide an accurate number
  of rows matched, so Sequel::Model usage on those adapters will now
  raise a NoExistingObject exception by default if you attempt to
  delete or update an instance that no longer exists in the database.

* Foreign key creation now works correctly without specifying the
  :key option when using MySQL with the InnoDB table engine.  InnoDB
  requires that you list the column explicitly, even if you are
  referencing the primary key of the table, so if the :key option is
  not given, the database schema is introspected to find the primary
  key for the table.  If you are attempting to create a table with
  a self-referential foreign key, it introspects the generator to
  get the primary key for the table.

* The sqlite adapter will now return 1/0 stored in boolean columns as
  true/false.  It will convert dates stored as Integers/Floats to
  Date objects by assuming they represent the julian date.  It will
  convert times stored as Integers/Floats to Sequel::SQLTime objects
  by assuming they represent a number of seconds. It will convert
  datetimes stored as Integers by assuming they represent a unix
  epoch time integer, and datetimes stored as Floats by assuming the
  represent the julian date (with fractional part representing the
  time of day).  These changes make Sequel handle SQLite's
  recommendations for boolean/date/time storage.

* The instance_hooks plugin's (before|after)_*_hook methods now return
  self so they can be used in a method chain.

* The list plugin now automatically adds new entries to the end of the
  list when creating the entries, if the position field is not
  specifically set.

* An identifier_output_method is now respected in the mysql2 adapter.

* NaN/Infinity Float values are now quoted correctly for input on
  PostgreSQL, and the postgres adapter correctly handles them on
  retrieval from the database.

* The :collate column option is now respected when creating tables or
  altering columns on MySQL.

* You can now force use of the TimestampMigrator when the
  IntegerMigrator would be used by default by calling
  TimestampMigrator.apply or .run.

* Mock adapter usage with a specific SQL dialect now uses the
  appropriate defaults for quoting identifiers.

* You can now disable the use of sudo in the rake install/uninstall
  tasks using the SUDO='' environment variable.

* A very misleading error message has been fixed when attempting
  to constantize an invalid string in the model inflector.

= Backwards Compatibility

* The sqlite adapter now typecasts columns that SQLite stores as
  INTEGER/REAL.  Previously, it only typecasted columns that
  SQLite stored as TEXT/BLOB.  For details about SQLite storage, see
  http://www.sqlite.org/datatype3.html.

  Any custom type conversion procs used with the sqlite adapter should
  be modified to work with Integer/Float objects in addition to String
  objects.

---

### Doc Release Notes 3.34.0 (`doc/release_notes/3.34.0.txt`)

= New PostgreSQL Extensions

* A pg_array extension has been added, supporting PostgreSQL's
  numeric and string array types.  Both single dimensional and
  multi-dimensional array types are supported.  Array values are
  returned as instances of Sequel::Postgres::PGArray, which is a
  delegate class of Array.  You can turn an existing array into
  a PGArray using Array#pg_array.

  If you are using arrays in model objects, you need to load
  support for that:

    DB.extend Sequel::Postgres::PGArray::DatabaseMethods

  This makes schema parsing and typecasting of array columns work
  correctly.

  This extension also allows you to use PGArray objects and arrays
  in bound variables when using the postgres adapter with pg.

* A pg_hstore extension has been added, supporting PostgreSQL's hstore
  type, which is a simple hash with string keys and string or NULL
  values.  hstore values are retrieved as instances of
  Sequel::Postgres::HStore, which is a delegate class of Hash.  You
  can turn an existing hash into an hstore using Hash#hstore.

  If you are using hstores in model objects, you need to load
  support for that:

    DB.extend Sequel::Postgres::HStore::DatabaseMethods

  This makes schema parsing and typecasting of hstore columns work
  correctly.

  This extension also allows you to use HStore objects and hashes
  in bound variables when using the postgres adapter with pg.

* A pg_array_ops extension has been added, making it easier to call
  PostgreSQL array operators and functions using plain ruby code.
  Examples:

    a = :array_column.pg_array
    a[1]              # array_column[1]
    a[1][2]           # array_column[1][2]
    a.push(1)         # array_column || 1
    a.unshift(1)      # 1 || array_column
    a.any             # ANY(array_column)
    a.join            # array_to_string(array_column, '', NULL)

  If you are also using the pg_array extension, you can turn
  a PGArray object into a query object, which allows you to run
  operations on array literals:

    a = [1, 2].pg_array.op
    a.push(3)               # ARRAY[1,2] || 3

* A pg_hstore_ops extension has been added, making it easier to call
  PostgreSQL hstore operators and functions using plain ruby code.
  Examples:

    h = :hstore_column.hstore
    h['a']             # hstore_column -> 'a'
    h.has_key?('a')    # hstore_column ? 'a'
    h.keys             # akeys(hstore_column)
    h.to_array         # hstore_to_array(hstore_column)

  If you are also using the pg_hstore extension, you can turn
  an HStore object into a query object, which allows you to run
  operations on hstore literals:

    h = {'a' => 'b'}.hstore.op
    h[a]               # '"a"=>"b"'::hstore -> 'a'

* A pg_auto_parameterize extension has been added for automatically
  using bound variables for all queries.  For example, it can take
  code such as:

    DB[:table].where(:column=>1)
  
  and do:

    SELECT * FROM table WHERE column = $1; -- [1]

  Note that automatically parameterizing queries is not generally
  faster unless the bound variables are large (i.e. long text/bytea
  values).  Also, there are multiple corner cases when automatically
  parameterizing queries, though most can be worked around by
  adding explicit casts.

* A pg_statement_cache extension has been added that works with the
  pg_auto_parameterize extension for automatically caching prepared
  statements and reusing them when using the postgres adapter with
  pg.  The combination of these two extensions makes it possible to
  take an entire Sequel application and turn most or all of the
  queries into prepared statements.

  Note that these two extensions do not necessarily improve
  performance.  For simple queries, they actually hurt performance.
  They do help for complex queries, but in all cases, it's faster
  to use Sequel's prepared statements API manually.

= Other New Extensions

* A query_literals extension has been added that makes the select,
  group, and order methods operate similar to the filter methods in
  that if they are given a regular string as their first argument,
  they treat it as a literal string, with additional arguments, if
  any, used as placeholder values.  This extension allows you to
  write code such as:

    DB[:table].select('a, b, ?' 2).group('a, b').order('c')
    # Without query_literals:
    #   SELECT 'a, b, ?', 2 FROM table GROUP BY 'a, b' ORDER BY 'c'
    # With query_literals:
    #   SELECT a, b, 2 FROM table GROUP BY a, b ORDER BY c

  Sequel's default handling in this case is to use literal strings,
  which is generally not desired and on some databases not even
  valid syntax.  In general, you'll probably want to use this
  extension for all of a database's datasets, which you can do via:

    Sequel.extension :query_literals
    DB.extend_datasets(Sequel::QueryLiterals)

  The next major version of Sequel (4.0.0) will probably integrate
  this extension into the core library.

* A select_remove extension has been added that adds
  Dataset#select_remove, for removing selected columns/expressions
  from a dataset:

    ds = DB[:table]
    # Assume table has columns a, b, and c

    ds.select_remove(:c)
    # SELECT a, b FROM table

    # Removal by column alias
    ds.select(:a, :b___c, :c___b).select_remove(:c)
    # SELECT a, c AS b FROM table 
    
    # Removal by expression
    ds.select(:a, :b___c, :c___b).select_remove(:c___b)
    # SELECT a, b AS c FROM table 
    
  This method makes it easier to select all columns except for the
  columns given.  This is common in cases where a table has a few
  large columns that are expensive to retrieve.  This method does
  have some corner cases, so read the documentation before using it.

* A schema_caching extension has added that makes it possible for
  Database instances to dump the cached schema metadata to a
  marshalled file, and load the cached schema metadata from the file.
  This can be significantly faster than reparsing the schema from the
  database, especially for databases with high latency.

  bin/sequel -S has been added to dump the schema for the given
  database to a file, and DB.load_schema_cache(filename) can be used
  to populate the schema cache inside your application.  This should
  be done after creating the Database object but before loading your
  model files.

  Note that Sequel does no checking to ensure that the cached schema
  currently reflects the state of the database.  That is up to the
  application.

* A null_dataset extension has been added, which adds
  Dataset#nullify for creating a dataset that will not issue a
  database query.  It implements the null object pattern for
  datasets, and is probably most useful in methods that must return
  a dataset, but can determine that such a dataset will never return
  a row.

= New Plugins

* A static_cache plugin has been added, allowing you to cache a model
  statically.  This plugin is useful for models whose tables do not
  change while the application is running, such as lookup tables.
  When using this plugin, the following methods will no longer require
  queries:

  * Primary key lookups (e.g. Model[1])
  * Model.all calls
  * Model.each calls
  * Model.map calls without an argument
  * Model.to_hash calls without an argument

  The statically cached model instances are frozen so they are not
  accidentally modified.

* A many_to_one_pk_lookup plugin has been added that changes the
  many_to_one association retrieval code to do a simple primary
  key lookup on the associated class in most cases.  This results
  in significantly better performance, especially if the
  associated model is using a caching plugin (either caching
  or static_cache).

= Core Extension Replacements

* Most of Sequel's core extensions now have equivalent methods defined
  on the Sequel module:

    :column.as(:alias)        -> Sequel.as(:column, :alias)   
    :column.asc               -> Sequel.asc(:column)
    :column.desc              -> Sequel.desc(:column)
    :column.cast(Integer)     -> Sequel.cast(:column, Integer)
    :column.cast_numeric      -> Sequel.cast_numeric(:column)
    :column.cast_string       -> Sequel.cast_string(:column)
    :column.extract(:year)    -> Sequel.extract(:year, :column)
    :column.identifier        -> Sequel.identifier(:column)
    :column.ilike('A%')       -> Sequel.ilike(:column, 'A%')
    :column.like('A%')        -> Sequel.like(:column, 'A%')
    :column.qualify(:table)   -> Sequel.qualify(:table, :column)
    :column.sql_subscript(1)  -> Sequel.subscript(:column, 1)
    :function.sql_function(1) -> Sequel.function(:function, 1)
    'some SQL'.lit            -> Sequel.lit('some SQL')
    'string'.to_sequel_blob   -> Sequel.blob('string')
    {:a=>1}.case(0)           -> Sequel.case({:a=>1}, 0)
    {:a=>1}.sql_negate        -> Sequel.negate(:a=>1)
    {:a=>1}.sql_or            -> Sequel.or(:a=>1)
    [[1, 2]].sql_value_list   -> Sequel.value_list([[1, 2]])
    [:a, :b].sql_string_join  -> Sequel.join([:a, :b])
    ~{:a=>1}                  -> Sequel.~(:a=>1)
    :a + 1                    -> Sequel.+(:a, 1)
    :a - 1                    -> Sequel.-(:a, 1)
    :a * 1                    -> Sequel.*(:a, 1)
    :a / 1                    -> Sequel./(:a, 1)
    :a & 1                    -> Sequel.&(:a, 1)
    :a | 1                    -> Sequel.|(:a, 1)

* You can now wrap any object in a Sequel expression using
  Sequel.expr.  This is similar to the sql_expr extension, but
  without defining the sql_expr method on all objects:

    1.sql_expr                -> Sequel.expr(1)

  The sql_expr extension now just has Object#sql_expr call
  Sequel.expr.

* Virtual Rows now have methods defined that handle the standard
  mathematical operators:

    select{|o| o.+(1, :a)} # SELECT (1 + a)

  the standard inequality operators:

    where{|o| o.>(2, :a)}  # WHERE (2 > a)

  and the standard boolean operators:

    where{|o| o.&({:a=>1}, o.~(:b=>1))} # WHERE ((a = 1) AND (b != 1))

  Additionally, there is now direct support for creating literal
  strings in instance_evaled virtual row blocks using `:

    where{a > `some crazy SQL`} # WHERE (a > some crazy SQL)

  This doesn't override Kernel.`, since virtual rows use a BasicObject
  subclass.  Previously, using ` would result in calling the SQL
  function named ` with the given string, which probably isn't valid
  syntax on most databases.

* You can now require 'sequel/no_core_ext' to load Sequel without the
  core extensions.  The previous way of setting the
  SEQUEL_NO_CORE_EXTENSIONS constant or environment variable before
  loading Sequel still works.

* The core extensions have been moved from Sequel's core library into
  an extension that is loadable with Sequel.extension.  This extension
  is still loaded by default for backwards compatibility.  However,
  the next major version of Sequel will no longer load this extension
  by default (though it will still be available to load manually).

* You can now check if the core extensions have been loaded by using
  Sequel.core_extensions?.

= Foreign Keys in the Schema Dumper

* Database#foreign_key_list has been added that gives an array of
  foreign key constraints on the table.  It is currently implemented
  on MySQL, PostgreSQL, and SQLite, and may be implemented on other
  database types in the future.  Each entry in the return array is
  a hash, with at least the following keys present:

  :columns :: An array of columns in the given table
  :table :: The table referenced by the columns
  :key :: An array of columns referenced (in the table specified by
          :table), but can be nil on certain adapters if the primary
          key is referenced.

  The hash may also contain entries for:

  :deferrable :: Whether the constraint is deferrable
  :name :: The name of the constraint
  :on_delete :: The action to take ON DELETE
  :on_update :: The action to take ON UPDATE

* The schema_dumper extension now dumps foreign key constraints on
  databases that support Database#foreign_key_list.  On such
  databases, dumping a schema migration will dump the tables in
  topological order, such that referenced tables always come before
  referencing tables.

  In case there is a circular dependency, Sequel breaks the
  dependency and adds separate foreign key constraints at the end
  of the migration.  However, when a circular dependency is broken,
  the migration can probably not be migrated down.

  Foreign key constraints can also be dumped as a separate migration
  using Database#dump_foreign_key_migration, similar to how
  Database#dump_indexes_migration works.

* When using bin/sequel -C to copy databases, foreign key constraints
  are now copied if the source database supports
  Database#foreign_key_list.

= Other New Features

* Dataset#to_hash_groups and #select_hash_groups have been added.
  These methods are similar to #to_hash and #select_hash in that they
  return a hash, but hashes returned by *_hash_groups methods have
  arrays of all matching values, unlike the *_hash methods which
  just use the last matching value. Example:

    DB[:table].all
    # => [{:a=>1, :b=>2}, {:a=>1, :b=>3}, {:a=>2, :b=>4}]

    DB[:table].to_hash(:a, :b)
    # => {1=>3, 2=>4}

    DB[:table].to_hash_groups(:a, :b)
    # => {1=>[2, 3], 2=>[4]}

* Model#set_fields and #update_fields now accept :missing=>:skip and
  :missing=>:raise options, allowing them to be used in more cases.
  :missing=>:skip skips missing entries in the hash, instead of
  setting the field to the default hash value.  :missing=>:raise
  raises an error for missing fields, similar to
  strict_param_setting = true.  It's recommended that these options
  be used in new code in preference to #set_only and #update_only.

* Database#drop_table? has been added, for dropping tables if they
  already exist.  This uses DROP TABLE IF EXISTS on the databases that
  support it.  Database#supports_drop_table_if_exists? has been added
  for checking whether the database supports that syntax.

* Database#create_join_table has been added that allows easy 
  creation of many_to_many join tables:

    DB.create_join_table(:album_id=>:albums, :artist_id=>:artists)

  This uses real foreign keys for both of the columns, uses a
  composite primary key of both of the columns, and adds an
  additional composite index of the columns in reverse order.  The
  primary key and additional index should ensure that almost all
  operations on the join table can benefit from an index.

  In terms of customization, the values in the hash can be hashes
  themselves for column specific options, and an additional options
  hash can also be given to override some of the default settings.

  Database#drop_join_table also exists and takes the same options
  as create_join_table.  It mostly exists to make it easy to
  reverse migrations that use create_join_table.

* Model#freeze has been added that freezes a model such that it
  works correctly in a read-only state.  Before, it used the standard
  Object#freeze, which broke some things that should work, and
  allowed changes that shouldn't be allowed (like modifying the
  instance's values).

* ConnectionPool#all_connections has been added, which yields each
  available connection in the pool to the block.  For threaded pools,
  it does not yield connections that are currently being used by
  other threads.  When using this method, it is important to only
  operate on the yielded connection objects, and not make any
  modifications to the pool itself.  The pool is also locked until
  the method returns.

* ConnectionPool#after_connect= has been added, allowing you to
  change a connection pool's after_connect proc after instantiating
  the pool.

* ConnectionPool#disconnection_proc= has been added, allowing you to
  change a connection pool's disconnection_proc after instantiating the
  pool.

* A Model.cache_anonymous_models accessor has been added, and can be
  set to false to disable the caching of classes created by
  Sequel::Model().  This caching is only useful if you want to reload
  the model's file without getting a superclass mismatch.  This
  setting is true by default for backwards compatibility, but may be
  changed to false in a later version, so you should manually set it to
  true if you are using code reloading.

* Model.instance_dataset has been added for getting the dataset used
  for model instances (a naked dataset restricted to a single row).

* Dataset#with_sql_delete has been added for running the given SQL
  string as a delete and returning the number of rows modified.  It's
  designed as a replacement for with_sql(sql).delete, which is slower
  as it requires cloning the dataset.

* The :on_update and :on_delete entries for foreign_key now accept
  string arguments which are used literally.

* Prepared statement objects now have a log_sql accessor that can be
  turned on to log the entire SQL statement instead of just the
  prepared statement name.

* Dataset#multi_replace has been added on MySQL.  This is similar to
  multi_insert, but uses REPLACE instead of INSERT.

* Dataset#explain has been added to MySQL.  You can use an
  :extended=>true option to use EXPLAIN EXTENDED.

* A Database#type_supported? method has been added on PostgreSQL to
  check if the database supports the given type:

    DB.type_supported?(:hstore)

* Database#reset_conversion_procs has been added to the postgres
  adapter, for use by extensions that modify the default conversion
  procs and want to have the database use the updated defaults.

* A Database#convert_infinite_timestamps accessor has been added to
  the postgres adapter, allowing you to return infinite timestamps as
  nil, a string, or a float.

* SQL::PlaceholderLiteralString objects can now use a placeholder
  array, where placeholder values are inserted between array elements.
  This is about 2.5-3x faster than using a string with ? placeholders,
  and allows usage of ? inside the array:

    Sequel.lit(["(", " ? ", ")"], 1, 2)  # (1 ? 2)

* SQL::Subscript#[] has been added for accessing members of a
  multi-dimensional array:

    Sequel.subscript(:column, 1)[2][3]  # column[1][2][3] 

* SQL::Wrapper has been added for wrapping arbitrary objects in a
  Sequel expression object.

* SQL::QualifiedIdentifier objects can now contain arbitrary Sequel
  expressions.  Before, they could only contain a few expression
  types.  This makes it easier to add extensions to support
  PostgreSQL row-valued types.

= Performance Improvements

* Model.[] when called with a primary key has been made about 110%
  faster for most models by avoiding cloning datasets.

* Model.[] when called without arguments or with a single nil argument
  is much faster as it now returns nil immediately instead of issuing
  a database query.

* Model#delete and Model#destroy have been made about 75% faster for
  most models by using a static SQL string.

* Model.new is now twice as fast when passed an empty hash.

* Model#set is now four times as fast when passed an empty hash.

* Model#this has been made about 85% faster by reducing the number of
  dataset clones needed from 3 to 1.

* Some proc activations have been removed, giving minor speedups when
  running on MRI.

= Other Improvements

* Database#uri and #url now return the connection string given
  to Sequel.connect.  Previously, they tried to reconstruct the
  url using the database's options, but that didn't work well in
  corner cases.

* Database#inspect now shows the URL and/or options given when
  connecting to the database.  Previously, it showed the URL, or
  all of the databases options if constructing the URL raised an
  error.

* Sequel no longer checks for prepared transactions support when
  using transactions unless a prepared transaction is specifically
  requested.

* The schema utility dataset cached in the Database object is now
  reset if you use Database#extend_datasets, ensuring that the new
  value will use the given extension.

* The prepared_statements* plugins now log the full SQL by default.
  Since the user doesn't choose the name of the prepared statements,
  it was often difficult to determine what SQL was actually run if
  you were only looking at a subsection of the SQL log.

* The nested_attributes plugin's delete/remove support now works
  correctly when a false value is given for _delete/_remove and
  strict_param_setting is true.

* The hook_class_methods and validation_class_methods plugins
  now work correctly when subclassing if the subclass attempts to
  create instances inside Model.inherited.

* The caching plugin has been refactored.  Model.cache_get_pk and
  cache_delete_pk have been added for retrieving/deleting from the
  cache by primary key.  Model.cache_key is now a public method.

* The typecast_on_load plugin now works correctly when saving
  new model objects when insert_select is supported.

* In the sql_expr extension, nil.sql_expr is no longer treated as
  a boolean value.  It is now treated as a value with generic type.

* The postgres adapter no longer issues a query to map type names to
  type oids if no named conversion procs have been registered.

* The postgres adapter now works around issues in ruby-pg by
  supporting fractional seconds for Time/DateTime values, and
  supporting SQL::Blob (bytea) values with embedded "\0" characters.

* The postgres adapter now supports pre-defining the PG_NAMED_TYPES
  and PG_TYPES constants.  This is so extensions can define them,
  so they don't have to load the postgres adapter file first. If
  extensions need to use these constants, they should do:

    PG_NAMED_TYPES = {} unless defined?(PG_NAMED_TYPES)
    PG_TYPES = {} unless defined?(PG_TYPES)

  That way they work whether they are loaded before or after the
  postgres adapter.

* PostgreSQL 8.2-9.0 now correctly add the RETURNING clause when
  building queries.  Sequel 3.31.0 added support for returning values
  from delete/update queries in PostgreSQL 8.2-9.0, but didn't change
  the literalization code to use the RETURNING clause on those
  versions.

* The jdbc/postgres adapter now converts Java arrays
  (Java::OrgPostgresqlJdbc4::Jdbc4Array) to ruby arrays.

* Tables and schemas with embedded ' characters are now handled
  correctly when parsing primary keys and sequences on PostgreSQL.

* Identifiers are now escaped on MySQL and SQLite. Previously they
  were quoted, but internal ` characters were not doubled.

* Fractional seconds for the time type are now returned correctly on
  jdbc (assuming they are returned as java.sql.Time values by JDBC).

* Multiple changes were made to ensure that Sequel works correctly
  when the core extensions are not loaded.

* Composite foreign key constraints are now retained when emulating
  alter_table operations on SQLite.  Previously, only single
  foreign key constraints were retained.

* An error is no longer raised when no indexes exist when calling
  Database#indexes on jdbc/sqlite.

* A possible SystemStackError has been fixed in the SQLite adapter,
  when trying to delete a dataset that uses a having clause and no
  where clause.

* ROLLUP/CUBE support now works correctly on Microsoft SQL Server
  2005.

* Unsigned tinyint types are now recognized in the schema dumper.

* Using primary_key :column, :type=>Bignum now works correctly on H2.
  Previously, the column created was not autoincrementing.

* Using a bound variable for a limit is now supported in the ibmdb
  adapter on ruby 1.9.

* Connecting to PostgreSQL via the swift adapter has been fixed when
  using newer versions of swift. 

* The mock adapter now handles calling the Database#execute methods
  directly (instead of via a dataset).

* The mock adapter now has the ability to have per-shared adapter
  specific initialization code executed.  This has been used to fix
  some bugs when using the shared postgres adapter.

* The pretty_table extension has been split into two extensions, one
  that adds a method to Dataset and one that just adds the
  PrettyTable class.  Also, PrettyTable.string has been added to get
  a string copy of the table.

* A spec_model_no_assoc task has been added for running model specs
  without the association plugin loaded.  This is to check that the
  SEQUEL_NO_ASSOCIATIONS setting works correctly.

= Deprecated Features to be Removed in Sequel 3.35.0

* Ruby <1.8.7 support is now deprecated.

* PostgreSQL <8.2 support is now deprecated.

* Dataset#disable_insert_returning on PostgreSQL is now deprecated.
  Starting in 3.35.0, RETURNING will now always be used to get the
  primary key value when inserting.

* Array#all_two_pairs? is now deprecated.  It was part of the core
  extensions, but the core extensions have been refactored to no
  longer require it.  As it doesn't specifically relate to creating
  Sequel expression objects, it is being removed.  The private
  Array#sql_expr_if_all_two_pairs method is deprecated as well.

= Other Backwards Compatibility Issues

* The generic Bignum type now uses bigint on SQLite, similar to
  other databases.  The integer type was previously used.  The only
  exception is for auto incrementing primary keys, which still use
  integer for Bignum as SQLite doesn't support autoincrementing
  columns other than integer.

* On SQLite, Dataset#explain now returns a string, similar to
  PostgreSQL (and now MySQL).

* When using the JDBC adapter, Java::OrgPostgresqlUtil::PGobject
  objects are converted to ruby strings if the dataset is set to
  convert types (the default setting).  This is to support the
  hstore extension, but it could have unforeseen effects if custom
  types were used.

* For PostgreSQL connection objects, #primary_key and #sequence now
  require their arguments are provided as already literalized
  strings.  Note that these methods are being removed in the next
  version because they will not be needed after PostgreSQL <8.2
  support is dropped.

* Database#uri and #url now return a string or nil, but never raise
  an exception.  Previously, they would either return a string
  or raise an exception.

* The Model @simple_pk and @simple_table instance variables should
  no longer be modified directly.  Instead, the setter methods should
  be used.

* Model.primary_key_lookup should no longer be called with a nil
  value.

* Logging of prepared statements on some adapters has been changed
  slightly, so log parsers might need to be updated.

* Dataset#identifier_append and #table_ref_append no longer treat
  literal strings and blobs specially.  Previously, they were treated
  as identifiers.

* Dataset#qualified_identifier_sql_append now takes 3 arguments, so
  any extensions that override it should be modified accordingly.

* Some internally used constants and private methods have been
  deleted:

    Database::CASCADE
    Database::NO_ACTION
    Database::SET_DEFAULTS
    Database::SET_NULL
    Database::RESTRICT
    Dataset::COLUMN_ALL

  or moved:

    MySQL::Dataset::AFFECTED_ROWS_RE -> MySQL::Database
    MySQL::Dataset#affected_rows -> MySQL::Database

* The sql_expr extension no longer creates the
  Sequel::SQL::GenericComplexExpression class.

---

### Doc Release Notes 3.35.0 (`doc/release_notes/3.35.0.txt`)

= New Features

* A dirty plugin has been added, which saves the initial value of
  the column when the column is changed, similar to
  ActiveModel::Dirty:

    artist.name                   # => 'Foo'
    artist.name = 'Bar'
    artist.initial_value(:name)   # 'Foo'
    artist.column_change(:name)   # ['Foo', 'Bar']
    artist.column_changes         # {:name => ['Foo', 'Bar']}
    artist.column_changed?(:name) # true
    artist.reset_column(:name)
    artist.name                   # => 'Foo'
    artist.column_changed?(:name) # false
    artist.update(:name=>'Bar')
    artist.column_changes         # => {}
    artist.previous_changes       # => {:name=>['Foo', 'Bar']}

* Database#create_table now respects an :as option to create a
  database based on the results of a query.  The :as option value
  should either be an SQL string or a dataset.

    DB.create_table(:new_foos, :as=>DB[:foos].where(:new=>true))

* The json_serializer and xml_serializer plugins can now serialize
  arbitrary arrays of model objects by passing an :array option
  to the to_json class method.  This works around an issue in
  ruby's JSON library where Array#to_json does not pass arguments
  given to it to the members of the array.

    Artist.to_json(:array=>[Artist[1]], :include=>:albums)

* You can now use the % (modulus) operator in the same way you
  can use the bitwise operators in Sequel:

    :column.sql_number % 1 # (column % 1)

* On PostgreSQL, you can now provide :only, :cascade, and :restart
  options to Dataset#truncate to use ONLY, CASCADE, and
  RESTART IDENTITY.  Additionally, you can now truncate multiple
  tables at the same time:

    DB.from(:table1, :table2).truncate(:cascade=>true)

* The :index option when creating columns in the schema generator
  can now take a hash of index options:

    DB.create_table(:foo){Integer :bar, :index=>{:unique=>true}}

* A Database#cache_schema accessor has been added, it can be set
  to false to have the Database never cache schema results.  This
  can be useful in Rails development mode, so that you don't need to
  restart a running server to have models pick up the new schema.

* Database#log_exception has been added for easier instrumentation.
  It is called with the exception and SQL query string for all
  queries that raise an exception.

* The Sequel.migration DSL now has a transaction method that forces
  transaction use for the given migration.

= Other Improvements

* Many theoretical thread-safety issues have been fixed for ruby
  implementations that don't use a global interpreter lock.
  Previously, Sequel relied on MRI's global interpreter lock for
  part of its thread safety, now it does manually locking in more
  places to avoid thread-safety issues on JRuby (and other ruby
  implementations without a global interpreter lock).

  No Sequel user ever reported a production error related to the
  previous thread-safety issues, and most of the issues fixed
  were so difficult to hit that even tests specifically designed
  to raise errors were unable to do so.

* Sequel.single_threaded = true now disables the mutex
  synchronization that enforces thread safety for additional
  performance in single threaded mode.

* Sequel's migrators now only attempt to use transactions by
  default if the underlying database supports transactional DDL.
  SQLite does support transactional DDL, but Sequel will not
  use transactions for SQLite migrations as it causes issues
  when emulating alter_table operations for tables with foreign
  keys.

* Errors that occur when rolling back database transactions are
  now handled correctly.  Previously, the underlying exception was
  raised, it wasn't correctly wrapped in a Sequel::DatabaseError,
  and if it was due to a database disconnection, the connection
  wasn't removed from the pool.

* Sequel no longer sets ruby instance variables on java objects,
  fixing warnings on JRuby 1.7 and attempting to be forward
  compatible with JRuby 2.0.

* Sequel now uses date and timestamp formats that are multilanguage
  and not DATEFORMAT dependent on Microsoft SQL Server.

* Sequel now correctly escapes backslash-carriage return-line feed
  on Microsoft SQL Server.

* Parsing the column default values in the oracle adapter no longer
  requires database superuser privileges.

* Sequel now correctly handles parsing schema for tables in other
  databases on MySQL.  Previously, it would always look in the
  current database.

* Sequel no longer doubles backslashes in strings by default.  It
  now only does so on MySQL, since that is the only database that
  appears to use backslashes for escaping.  This fixes issues with
  backslashes being doubled on some of the less commonly used
  adapters.

* The pg_auto_parameterize extension now works correctly when
  using cursors.

* Dataset#truncate now raises an Error if you attempt to do so
  on a dataset that uses HAVING.  Previously, it only checked for
  WHERE.

* The schema dumper now recognized the identity type.

= Backwards Compatibility

* Association reflections now store cached information in a
  separate subhash due to the thread-safety changes.  Any code
  accessing an association reflection should always call the
  related method to get the cached data instead of checking
  for a specific location in the hash.

* Association reflection internals for many_through_many associations
  changed significantly, any code that accesses the edge information
  in the reflection will need to be changed to use the new methods
  instead of accessing the old values directly.

* The features deprecated in 3.34.0 have now been removed:
  * Ruby <1.8.7 support
  * PostgreSQL <8.2 support
  * Dataset#disable_insert_returning on PostgreSQL
  * Array#all_two_pairs? and #sql_expr_if_all_two_pairs

---

### Doc Release Notes 3.36.0 (`doc/release_notes/3.36.0.txt`)

= New Features

* An eager_each plugin has been added, which automatically makes
  eagerly loaded datasets do eager loading if you call #each (or
  another Enumerable method) instead of #all.  By default, if you
  call #each on an eager dataset, it will not do eager loading,
  and if you call #each on an eager_graph dataset, you will
  get plain hashes with columns from all joined tables instead of
  model objects.  With this plugin, #each on both eager and
  eager_graph datasets will do eager loading.

* The nested attributes plugin now supports composite primary keys
  in associated records.  Additionally, it now deals better with
  natural primary keys in associated records.  There is a new
  :unmatched_pk option that can be set to :create if you want to
  create new associated records when the input hash contains
  primary key information that doesn't match one of the existing
  associated objects.

  The nested attributes plugin now also supports a :transform option.
  If given, this option is called with the parent object and the
  input hash given for each associated record passed into the
  nested attributes setter.  The callable should return the hash
  of attributes to use.

* Model#from_json in the json_serializer plugin now takes an options
  hash and recognizes the :fields option.  If the :fields option is
  given, it should be an array of field names, and set_fields is
  called with the array instead of using set.  This allows you to
  easily filter which fields in the hash are set in the model
  instance.  The entire options hash is also passed to set_fields
  if :fields is present, so you can additionally use the :missing =>
  :raise or :missing => :skip options that set_fields supports.

* The Dataset#to_json method in the json_serializer plugin now
  respects :root=>:collection and :root=>:instance options.  If
  :root=>:collection is given, only the collection is wrapped in a
  hash, and if :root=>:instance is given, only the instances are
  wrapped in a hash.  For backwards compatibility, both the
  instances and collection are wrapped in a hash:

    Model.to_json(:root=>true)
    # {"models":[{"model":{"id":1}}]}

    Model.to_json(:root=>:collection)
    # {"models":[{"id":1}]}

    Model.to_json(:root=>:instance)
    # [{"model":{"id":1}}]

  Wrapping both the collection and instance in a root by default
  is probably an undesired behavior, so the default for :root=>true
  may change in the next major version of Sequel.  Users who want
  the current behavior should switch to using :root=>:both.

* The schema_dumper extension now respects an :index_names option
  when dumping.  This option can be set to false to never dump the
  index names.  It can also be set to :namespace, in which case if
  the database does not have a global index namespace, it will
  automatically prefix the name of the index with the name of the
  table.

  Database#global_index_namespace? was added to check if the
  database uses a global index namespace.  If false, index names are
  probably namespaced per table (MySQL, MSSQL, Oracle).

* :each is now a valid prepared statement type.  This prepared
  statement type requires a block when you call the statement, and
  iterates over the records of the statement a row at a time.
  Previously, there wasn't a way to iterate over the records of a
  prepared statement a row at a time, since the :select and :all
  types collect all rows into an array before iterating over them.

* A :connection_handling=>:queue option is now respected for
  database objects, and changes the threaded connection pools to use
  a queue instead of a stack as the data structure for storing
  available connections.  A queue does not perform as well as a
  stack, but reduces the likelihood of stale connections.

  It is possible that Sequel will change in the future from using a
  stack by default to using a queue by default, so any users who
  specifically desire a stack to be used should specify the
  :connection_handling=>:stack option.

* Sequel::Migrator now supports is_current? class method to check
  if there are no outstanding migrations to apply.  It also supports
  a check_current class method, which raises an exception if there
  are outstanding migrations to apply.

* A pg_json extension has been added, supporting PostgreSQL's 9.2
  json type, similarly to the pg_array and pg_hstore extensions.
  Note that with the current PostgreSQL json code, the root object
  can be a string or number, but ruby's json library requires the
  root json value to be an object or array.  So you will probably
  get an exception if you attempt to retrieve a PostgreSQL json
  value that ruby's JSON library won't parse.

* A pg_inet extension has been added, which automatically typecasts
  PostgreSQL inet and cidr types to ruby IPAddr objects on retrieval.

* Database#transaction on PostgreSQL now recognizes :read_only and
  :deferrable options, and can use them to set the READ ONLY and
  DEFERRABLE transaction flags.  A :synchronous option is also
  recognized, which can be set to true, false, :local, or
  :remote_write, and sets the value of synchronous_commit just for
  that transaction.

* When adding and dropping indexes on PostgreSQL, a :concurrently
  option can be used to create or drop the index CONCURRENTLY, which
  doesn't require a full write table lock.

* When dropping indexes on PostgreSQL, :if_exists and :cascade options
  are now recognized.

* When using alter_table set_column_type on PostgreSQL, the :using
  option is respected, and can be used to force a specific conversion
  from the previous value to the new value with the USING syntax.

* On MySQL, you can now set an :sql_mode option when connecting.  This
  can be a string or symbol or an array of them, and each should match
  one of MySQL's sql_modes.  MySQL's default SQL mode is fairly loose,
  and using one of the strict sql modes is recommended, but for
  backwards compatibility, Sequel will not set a specific SQL mode by
  default.  However, that may change in the next major version of
  Sequel, so to be forwards compatible you should set :sql_mode=>nil
  if you do not desire a strict SQL mode to be set automatically.

* Partial indexes are now supported on Microsoft SQL Server 2008
  (SQL Server refers to them as filtered indexes).  Attempting to
  use a partial index on an earlier version of SQL Server will
  result in the database raising an exception.

* A jdbc/progress adapter has been added, supporting the Progress
  database via the jdbc adapter.

= Other Improvements

* Dataset#get now works correctly if you pass it a nil or false
  argument.  Previously, it ignored the argument and used the block
  instead.  If you want to use the block argument, you should not
  pass in a regular argument.

* Database#call now passes any blocks given to it to the underlying
  prepared statement object.  Before, a passed block was ignored.

* Sequel::Model.db is no longer set automatically when creating
  an anonymous class with an associated database object.  This fixes
  cases where a library would create namespaced models, and the
  database used by the library would be set as the default for the
  user's application code.

* Model *_to_one association setters are now no-ops if you pass a
  value that is the same as the cached value.  This fixes issues with
  reciprocal associations getting reordered, and is better
  for performance.

  For cases where the old behavior is desired, the
  set_associated_object_if_same? method can be overridden to return
  true for object.  If you are manually setting objects in the
  associations cache before calling the setter method, you may want
  to set that.

* The dirty plugin no longer affects the return value of refresh
  and lock!.  Internal changes should now help ensure that plugins
  don't affect the return values of these methods.

* Sequel now supports JRuby 1.7's new exception handling, fixing
  exception handling when connecting in the jdbc adapter.

* When dumping unsigned integer types in the schema dumper, if the
  unsigned values could overflow a 32-bit signed integer type,
  the generic Bignum class is used as the type.  This should fix
  issues when copying a database containing an unsigned 32-bit
  integer column with values between 2^31 and 2^32-1.

* In the optimistic_locking plugin, attempting to refresh and
  save after a failed save now works correctly.  Before, the second
  save would never modify a row.

* Time types on jdbc/postgres are now typecasted accurately on
  retrieval, before they could be off by up to a millisecond due to
  floating point issues.

* Disconnect detection in the mysql2 adapter has been improved.

* The jdbc/mysql, do/mysql, and swift/mysql adapters all now support
  the :timeout option to set the MySQL wait_timeout.

* Savepoints in prepared transactions are now supported on MySQL
  5.5.23+, since the bug that caused them to be unsupported starting
  in 5.5.13 has been fixed.

* Parsing foreign key metadata for tables with an explicit
  schema now works correctly on PostgreSQL.

* bin/sequel -C now namespaces indexes automatically when copying
  from a database without a global index namespace to a database
  with a global index namespace.

* Indexes are now dropped in reverse order that they were added in
  the schema_dumper.

* The Model typecasting code works around bugs in objects where
  object.==('') would raise an exception instead of returning false.

* A better error message is used if an invalid JDBC URL is
  provided and the JDBC driver's new.connect method returns NULL.

* A document describing Sequel's object model has been added,
  describing the objects Sequel uses to represent SQL concepts.

* Most adapter specific options to Database methods are now mentioned
  in the main Database method RDoc.

= Backwards Compatibility

* The nested_attributes plugin internals changed significantly.  If
  you were overriding one of the nested_attributes* private methods
  and calling super to get the default behavior, you may have to
  update your code.

* Database#case_sensitive_like has been removed on SQLite.  This
  method never worked correctly, it always returned false even if
  the case_sensitive_like PRAGMA was set.  That's because SQLite
  doesn't offer a getter for this PRAGMA, only a setter.  Note that
  Database#case_sensitive_like= still exists and works correctly.

* Database#single_value has been removed from the native SQLite
  adapter.  This method was designed for internal use, and hasn't
  been used for some time.  Any current users of the method should
  switch to Dataset#single_value.

* The private Database#defined_columns_for method in the SQLite
  adapter no longer takes an options hash.

* A couple jdbc/postgres adapter methods are now private.  Previously,
  the jdbc/postgres adapter overrode some private superclass methods
  but left the methods public.

* When using the optimistic_locking plugin, refreshing inside a
  before_update method after calling super will now result in the
  lock checking being skipped.

* The private Model#_refresh no longer returns self, so external
  plugins should no longer rely on that behavior.

---

### Doc Release Notes 3.37.0 (`doc/release_notes/3.37.0.txt`)

= New Features

* Database#extension and Dataset#extension have been added and
  make it much easier to use extensions that just define modules,
  where you previously had to manually extend a Database or
  Dataset object with the module to get the extension's behavior.
  These methods operate similarly to model plugins, where you just
  specify the extension symbol, except that you can specify multiple
  extensions at once:

    DB.extension(:pg_array, :pg_hstore)

  For databases, these modify the Database itself (and
  potentially all of its datasets).  Dataset#extension operates
  like other dataset methods, returning a modified clone of
  the dataset with the extension added:

    dataset = dataset.extension(:columns_introspection)

  Dataset#extension! has also been added for modifying the
  receiver instead of returning a clone.

  Not all extensions are usable by Database#extension or
  Dataset#extension, the extension has to have specific support
  for it.  The following extensions support both
  Database#extension and Dataset#extension:

  * columns_introspection
  * query_literals
  * split_array_nil

  The following extensions support just Database#extension:

  * arbitrary_servers
  * looser_typecasting
  * pg_array
  * pg_auto_parameterize
  * pg_hstore
  * pg_inet
  * pg_interval
  * pg_json
  * pg_range
  * pg_statement_cache
  * server_block

  Any user that was loading these extensions with Sequel.extension
  and then manually extending objects with the extension's module
  is encouraged to switch to Database#extension and/or
  Dataset#extension.

* Dataset join methods now respect a :qualify=>:deep option
  to do deep qualification of expressions, allowing qualification
  of subexpressions in the expression tree.  This can allow you
  to do things like:

     DB[:a].join(:b, {:c.cast(Integer)=>:d.cast(Integer)},
                 :qualify=>:deep)
     # SELECT * FROM a INNER JOIN b
     # ON (CAST(b.c AS INTEGER) = CAST(a.d AS INTEGER))

  For backwards compatibility, by default Sequel will only do
  automatic qualification if the arguments are simple symbols.
  This may change in a future version, if automatic qualification
  of only symbols is desired, switch to using :qualify=>:symbol.
  
  You can also choose to do no automatic qualification using the
  :qualify=>false option.

* All of Sequel's model associations now work with key expressions
  that are not simple column references, without creating a fully
  custom association.  So you can create associations where the
  primary/foreign key values are stored in PostgreSQL array or
  hstore columns, for example.

* The pg_array extension has now been made more generic, so that it
  is easy to support array types for any scalar type that is
  currently supported.  All scalar types that Sequel's postgres
  adapter supports now have corresponding array types supported in
  the pg_array extension.  So if you load the pg_array extension and
  return a date array column, the returned values will be arrays of
  ruby Date objects.

  Other pg_* extensions that add support for PostgreSQL-specific
  scalar types now support array versions of those types if the
  pg_array extension is loaded first.

* A pg_range extension has been added, making it easy to deal
  with PostgreSQL 9.2+'s range types.  As ruby's Range class does
  not support all PostgreSQL range type values (such as empty ranges,
  unbounded ranges, or ranges with an exclusive beginning), range
  types are returned as instances of Sequel::Postgres::PGRange, which
  has an API similar to Range.  You can turn a PGRange into a Range
  using PGRange#to_range, assuming that the range type value does not
  use features that are incompatible with ruby's Range class.

  The pg_range extension supports all range types supported by
  default in PostgreSQL 9.2, and makes it easy to support custom
  range types.

* A pg_range_ops extension has been added, which adds DSL support for
  PostgreSQL range operators and functions, similar to the
  pg_array_ops and pg_hstore_ops extensions.

* A pg_interval extension has been added, which makes Sequel return
  PostgreSQL interval types as instances of ActiveSupport::Duration.
  This is useful if you want to take the interval value and use it in
  calculations in ruby (assuming you load the appropriate parts of
  ActiveSupport).

* A split_array_nil extension has been added, which changes how Sequel
  compiles IN/NOT IN expressions with arrays with nil values.

    where(:col=>[1, nil])
    # Default:
    #   WHERE (col IN (1, NULL))
    # with split_array_nil extension:
    #   WHERE ((col IN (1)) OR (col IS NULL))

    exclude(:col=>[1, nil])
    # Default:
    #   WHERE (col NOT IN (1, NULL))
    # with split_array_nil extension:
    #   WHERE ((col NOT IN (1)) AND (col IS NOT NULL))

* The nested_attributes plugin now allows the :fields option to
  be a proc, which is called with the associated object and should
  return an array of allowable fields.

* You can now specify the graph alias base when using eager_graph on
  a per-call basis.  Previously, it could only be set on a per
  association basis.  This is helpful if you have multiple
  associations to the same class, and are cascading the eager graph to
  dependent associations of that class for both of the associations.
  Previously, there was no way to manually give descriptive names to
  the tables in the cascaded associations, but you can now do so
  by passing the association as an Sequel::SQL::AliasedExpression
  instance instead of a plain Symbol.  Here's a usage example:

    ds = Game.eager_graph(:winner=>:players.as(:winning_players),
                          :loser=>:players.as(:losing_players)).
          where(:winning_players__name=>'A',
                :losing_players__name=>'B')

* many_through_many associations now differentiate between column
  references and method references, by supporting the
  :left_primary_key_column and :right_primary_key_method options that
  many_to_many associations support.

* Custom :eager_loader procs that accept a single hash argument now
  have an additional entry passed in the hash, :id_map, which is
  easier to use than the :key_hash entry (which is still present for
  backwards compatibility).  Anyone with custom :eager_loader procs is
  encouraged to switch from using :key_hash to :id_map.

* You can now override the create_table/alter_table schema generators
  per database/adapter.  This allows for database specific generator
  subclasses, which have methods for unique features for that
  database.

* You can now setup exclusion constraints on PostgreSQL using the
  create_table and alter_table schema generators:

    DB.create_table(:t) do
      ...
      exclude([[:col1, '&&'], [:col2, '=']])
      # EXCLUDE USING gist (col1 WITH &&, col2 WITH =)
    end

  One common use for exclusion constraints is to make sure that no two
  rows have overlapping values/ranges/circles.

* When adding foreign key constraints to an existing table on
  PostgreSQL, you can use the :not_valid option to mark the constraint
  as not yet valid.  This will make it so that future changes to the
  table need to respect the foreign key constraint, but existing rows
  do not.  After cleaning up the existing data, you can then use the
  alter_table validate_constraint method to mark the constraint as
  valid.

* An eval_inspect extension has been added that attempts to do
  do the following for Sequel::SQL::Expression instances:

    eval(obj.inspect) == obj # => true

  There are a lot of cases that this extension does not handle, but
  it does a decent job in most cases.  This is currently only used
  internally in a specific case in the schema_dumper extension.

= Other Improvements

* The filter by associations support now respects the method
  reference vs column reference distinction that other parts of the
  association code have respected since 3.32.0.

* In the nested_attributes plugin, new one_to_one associated
  values are saved once instead of twice.  Previously it attempted to
  save them before they were associated to the current model object,
  which can violate some validations/constraints.

* When saving an associated object in the one_to_one association
  setter method, Sequel no longer adds an unnecessary filter
  condition when nullifying the foreign key for existing rows
  in the associated table.

* The list plugin's before_create method now calls super, which
  fixes usage when other plugins that define before_create are loaded
  before it.

* In the pg_array extension, when typecasting an Array to PGArray,
  a recursive map is done on the input array to convert each value
  in the input array to the expected type, using the typecasting
  method that would be used for the scalar value.  For example, for
  model objects, where ids is an integer array column:

   model.set(:ids=>['1', '2']).ids.to_a # => [1, 2]

* The pg_array extension now correctly handles bytea arrays used
  in bound variables.

* The pg_array extension no longer uses the JSON-based parser for
  floating point types, since it doesn't handle NaN and Infinity
  values correctly.

* When typecasting in the pg_array extension, PGArray values are
  only returned verbatim if they have a matching database type.
  Otherwise, the underlying array is rewrapped in a new PGArray
  value with the correct database type.

* H2 clob types are now recognized as strings instead of blobs.
  Previously the code attempted to do this, but it didn't do so
  correctly.

* The jdbc/postgres adapter now converts scalar values of
  the array to the appropriate type.  Previously, if you retrieved
  a date array, you got back a ruby array of JavaSQL::SQL::Date
  instances.  Now, you get back a ruby array of ruby Date instances.

* The schema_dumper extension now dumps migrations as change
  migrations, instead of separate up/down migrations, resulting in
  simpler code.

* When dumping non-integer foreign keys in the schema dumper, an
  explicit type is now used.  Previously, the column would have been
  dumped as an integer column.

* When dumping unsigned integer columns in the schema dumper, add a
  column > 0 constraint in the dumped migration.

* On Microsoft SQL Server, when updating a dataset with a limit,
  the limit is now respected.

* When emulating offset using the ROW_NUMBER window function,
  do not require that the dataset be ordered.  If an order is
  not provided, default to ordering on all of the columns in
  the dataset.  If you want to override the default order used
  in such a case, you need to override the default_offset_order
  method for the dataset.

* On SQLite, casting to Date/Time/DateTime now calls an SQLite
  date/datetime function instead of using a cast, as SQLite treats
  such a cast as a cast to integer.

* When using JRuby 1.6 in ruby 1.9 mode and typecasting a time
  column, workaround a bug where Time#nsec is 0 even though
  Time#usec is not.

* The odbc/mssql adapter now correctly handles the case where
  SCOPE_IDENTITY returns NULL after an insert.

* bin/sequel now accepts multiple -l options for logging to multiple
  output files.

* In addition to Sequel's rigorous pre-push testing, Sequel now
  also uses TravisCI for continuous integration testing across
  a wider range of ruby implementations.

= Backwards Compatibility

* The keys in the :key_hash entry passed to the :eager_loader proc
  are now method references instead of column references.  For most
  associations, they are the same thing, but for associations using
  the :key_column/:primary_key_column/:left_primary_key_column
  options, the values could be different.  If you were using one
  of those options and had a custom eager_loader, you should switch
  from indexing into the :key_hash option to just using the :id_map
  option.

* The :key_hash entry passed to the :eager_loader proc is now no
  longer guaranteed to contain key maps for associations other than
  the one currently being eagerly loaded.  Previously, it contained 
  key maps for all associations that were being eagerly loaded.  If
  you have a custom :eager_loader proc that accessed a key map for
  a separate association that was being loaded concurrently, you'll
  now have to build the key map manually if it doesn't exist.

* If you previously explicitly specified an :eager_loader_key option
  when defining an association, you may need to change it so that it
  is a method reference instead of a column reference, or possibly
  just omit the option.

* If you have a custom :eager_loader proc for an association where
  the default :eager_loader_key option references a method that
  the model does not respond to (or raises an exception), you may
  need to specify the :eager_loader_key=>nil option.

* In the pg_auto_parameterize extension, String values are no longer
  automatically casted to text.  This is because the default type of
  a string literal in PostgreSQL is unknown, not text.  This makes it
  much less likely to require manual casts, but has the potential to
  break existing code relying on the automatic cast to text.  As a
  work around, any query that can no longer be automatically
  parameterized after this query just needs to add manual casting
  to text.

* Sequel now raises an exception if you attempt to clone associations
  with different types, except if one type is one_to_many and the
  other is one_to_one.  Cloning from other types was usually a bug,
  and raising an exception early will make it much easier to track
  such bugs down.

* When running the plugin/extension and PostgreSQL adapter specs,
  a json library is now required.

* The json/postgres adapter array typecasting internals have been
  modified, if you were relying on the internals, you may need to
  update your code.

* The pg_array extension internals changed significantly.  PGArray
  no longer has any subclasses by default, as parsing is now done
  in separate objects.  Anyone relying on the pg_array internals
  will need to update their code.

* The postgres adapter no longer sets up type conversion of int2vector
  and money types, since in both cases the conversion was incorrect in
  most cases.  These types will now be returned as strings.  If you are
  relying on the conversion, you'll need to add your own custom type
  procs.

---

### Doc Release Notes 3.38.0 (`doc/release_notes/3.38.0.txt`)

= New Features

* A pg_row extension has been added that supports PostgreSQL's
  row-valued/composite types.  You can register support for
  specific row types:

    DB.register_row_type(:address)

  Then you can create values of that row type:

    ad = DB.row_type(:address, ['555 Foo St.', 'Bar City', '98765'])
    # or
    ad = DB.row_type(:address, :street=>'555 Foo St.',
                          :city=>'Bar City', :zip=>'98765')

  Which you can use in your datasets:

    DB[:people].insert(:name=>'Me', :address=>ad)
  
  If you are using the native postgres adapter, when retrieving
  row type values, they will be returned as instances of the row
  type, which are hash-like objects:

    ad = DB[:people].get(:address)
    ad[:street] # => '555 Foo St.'
    ad[:city]   # => 'Bar City'
    ad[:zip]    # => '98765'

  If you are also using the pg_array extension, then arrays of
  composite types are supported automatically.  Composite
  types can also include arrays of other types as well as other
  composite types, though recursive composite types are not
  allowed by PostgreSQL.

  Using arrays and composite types brings one of the benefits
  of document databases to PostgreSQL, allowing you to store
  nested structures inside a single row.

* A pg_row_ops extension has been added that adds DSL support
  for accessing members of row-valued/composite types. You
  first create a row op:

    r = Sequel.pg_row_op(:row_column)

  Then you can get DSL support for accessing members of that
  row_column via the #[] method:

    r[:a] # (row_column).a

  This works with composite types containing composite types:

    r[:a][:b] # ((row_column).a).b

  When used in conjunction with the pg_array_ops extension,
  there is support for composite types that include arrays,
  as well as arrays of composite types:

    r[1][:a] # (row_column[1]).a
    r[:a][1] # (row_column).a[1]

  The extension offers additional support for referencing
  a table's type when it contains a column with the same
  name, see the RDoc for details.

* A pg_row plugin has been added, that works with the pg_row
  extension, and allows you to represent row-valued types as
  Sequel::Model objects (instead of the hash-like objects
  they use by default).  In your model class, you load the
  plugin:

    class Address < Sequel::Model(:address)
      plugin :pg_row
    end

  Then you can use Address instances in your datasets:
  
    ad = Address.new(:street=>'555 Foo St.',
                     :city=>'Bar City', :zip=>'98765')
    DB[:people].insert(:name=>'Me', :address=>ad)

  And if you are using the native postgres adapter, the dataset
  will return the type as a model instance:

    ad = DB[:people].get(:address)
    ad.street # => '555 Foo St.'
    ad.city   # => 'Bar City'
    ad.zip    # => '98765'
 
* A pg_typecast_on_load plugin has been added.  This plugin is
  designed for use with the jdbc/postgres, do/postgres, and
  swift/postgres adapters, and it is similar to the
  typecast_on_load plugin.  However, while the typecast_on_load
  plugin uses setter methods, the pg_typecast_on_load plugin
  uses the same code that the native postgres adapter uses for
  typecasting.

* The tinytds adapter now supports a :textsize option to override
  the default TEXTSIZE setting.  The FreeTDS default is fairly
  small (~64k), so if you want to use large blob or text columns,
  you should probably set this to a value larger than the
  largest text/blob you want to use.

* Sequel.expr when called with a symbol now splits the symbol and
  returns an Identifier, QualifiedIdentifier, or AliasedExpression, 
  depending on the content of the symbol.  Previously, it only
  wrapped the symbol using a Wrapper.

* Identifier#* and QualifiedIdentifier#* when called without any
  argument now represent a selection of all columns from the
  represented table:

    Sequel.expr(:table).*          # table.*
    Sequel.expr(:schema__table).*  # schema.table.*

  This makes it easier to represent the selection of all columns
  in a table without using the core extensions.

* Model#values now has a Model#to_hash alias.

* SQL::Blob values now have as, cast, and lit methods even if the
  core extensions are not loaded.

= Other Improvements

* When loading multiple pg_* extensions into a Database instance,
  the conversion procs are only reset once instead of once per
  extension.

* All adapters that access PostgreSQL now store type conversion
  procs, similar to the native postgres adapter.  This has been
  added to make it easier to write extensions that support
  advanced PostgreSQL types.

* Database#schema output on PostgreSQL now includes the type oid
  for each column.

* You can now register custom array types to specific Database
  instances, using the :type_procs and :typecast_methods_module
  options, so it is now possible to have custom array types
  without affecting global state.

* Dropping of columns with defaults now works correctly on
  Microsoft SQL Server.  Before, it would fail as the related
  constraint was not dropped first.

* The MySQL type "double(x,y)" is now recognized as a float type.

* The jdbc/jtds and jdbc/derby adapters now handle nil prepared
  statement values in more cases.

* Blob prepared statement arguments are now handled correctly on
  jdbc/db2 and jdbc/oracle.

* Sequel now works around a Time#nsec bug in JRuby 1.6 ruby 1.9 mode
  when using Time values in prepared statements in the jdbc adapter.

* Java::JavaUtil::UUID types are now returned as ruby strings
  when converting types in the jdbc adapter.

* Real boolean literals are now used on derby 10.7+.  On derby <10.7
  Sequel still uses (1 = 1) and (1 != 1) for true and false.  This
  allows you to use boolean columns with a true/false default on
  derby 10.7+.

* Clobs are now treated as string types instead of blobs on derby,
  since treating clob as blob doesn't work there.

* The swift adapter now supports an output identifier method.

* The swift adapter now returns blobs as SQL::Blob instances.

* The schema_dumper extension no longer produces code that requires
  the core extensions.

* All of Sequel's specs now run without the core extensions loaded,
  ensuring that none of the internals depend on the core extensions.
  The only exception is the specs for the core extensions themselves.

= Backwards Compatibility

* The pg_* extensions no longer modify core classes if the
  core_extensions extension is not loaded.  All methods they added now
  have equivalent methods on the main Sequel module:

    Sequel.pg_array
    Sequel.pg_array_op
    Sequel.hstore
    Sequel.hstore_op
    Sequel.pg_json
    Sequel.pg_range
    Sequel.pg_range_op

* The Sequel::SQL::IdentifierMethods module has been removed.  This
  module was only included in Symbol if the core_extensions were
  enabled.  Since it only defined a single method, now the core
  extensions just define that method directly on Symbol.

* The swift adapter now requires swift-db-{postgres,mysql,sqlite3}
  gems instead of the swift gem.  swift/postgres requires
  swift-db-postgres 0.2.0+, swift/sqlite requires swift-db-sqlite
  0.1.2+, and swift/mysql requires swift-db-mysql.

* Sequel will no longer typecast a string to a PostgreSQL array
  or hstore column in a model column setter.  This is because the
  parsers that Sequel uses were designed to support only
  PostgreSQL's output format.  It's unlikely that a user would
  provide that format for typecasting, and while there aren't known
  security issues with the parsers, they were not designed to handle
  arbitrary user input, so typecasting from string is no longer
  allowed and will now raise an error.

  The only reason such typecasting was allowed in the first place
  was to work around issues in the jdbc/postgres, do/postgres, and
  swift/postgres adapters, using the the typecast_on_load plugin.
  If you were previously using the typecast_on_load plugin for
  hstore or array columns, you need to switch to using the new
  pg_typecast_on_load plugin.

* The private get_conversion_procs method in the postgres adapter
  no longer accepts an argument.

* The Sequel::Postgres::PGArray::DatabaseMethods singleton
  define_array_typecast_method method has been removed.  This
  method was designed for internal use.

* The change to make Sequel.expr split symbols can cause the
  following type of code to break:

    Sequel.expr(:column___alias).desc

  This is because expr now returns an AliasedExpression, which
  doesn't support the desc method.  However, as you can't
  apply an order to an aliased expression, nobody should be
  relying on this.

---

### Doc Release Notes 3.39.0 (`doc/release_notes/3.39.0.txt`)

= New Features

* A constraint_validations extension and plugin have been added,
  which allow you to define validations when creating tables,
  which are enforced by database constraints, and have those
  validations be automatically discovered and used by your
  Sequel::Model classes.

  The extension is designed to be used in your migrations/schema
  modification code:

    DB.extension(:constraint_validations)
    DB.create_constraint_validations_table
    DB.create_table(:foos) do
      primary_key :id
      String :name

      validate do
        min_length 5, :name
      end
    end

  This creates a database CHECK constraint that ensures that the
  minimum length for the column is 5 characters.  It also adds
  metadata about the validation to the
  sequel_constraint_validations table.

  To have the model class automatically create validations, just
  include the plugin in the model:

    class Foo < Sequel::Model
      plugin :constraint_validations
    end

  Note that MySQL does not enforce CHECK constraints (it parses
  but ignores them), so using the extension on MySQL does not
  actually enforce constraints at the database level, though it
  still does support the automatic model validations if the plugin
  is used.

* Dataset#count now takes an argument or a virtual row block,
  allowing you to do:

    DB[:table].count(:column_name)
    DB[:table].count{function_name(column1, column2)}

  When count is given an argument, instead of returning the total
  number of rows, it returns the number of rows where the
  argument has a non-NULL value.

* Database#copy_into has been added to the postgres adapter when
  the pg driver is being used, and can be used for very fast
  inserts into tables if you already have the input preformatted
  in PostgreSQL text or CSV format.

* set_table_not_null has been added to the alter table generator,
  for a nicer API:

    alter_table(:t){set_column_not_null :col}
    # instead of
    alter_table(:t){set_column_allow_null :col, false}

  Additionally, set_column_allow_null now defaults the second
  argument to true for a nicer API:

    alter_table(:t){set_column_allow_null :col}
    # instead of
    alter_table(:t){set_column_allow_null :col, true}

* Database#supports_regexp? has been added for checking if the
  database supports Regexp in filters.  Currently, only MySQL and
  PostgreSQL support Regexps.

  Attempting to use a Regexp on a database that doesn't support it
  now raises an error when attempting to generate the SQL, instead
  of sending invalid SQL to the database.

* Sequel.char_length has been added for a cross platform
  char_length function (emulated when char_length is not supported
  natively by the database).

* Sequel.trim has been added for a cross platform trim function
  (emulated when trim is not supported natively by the database).

* ValidationFailed and HookFailed exceptions now have a model method
  that returns the model instance related to the exception.  This
  makes it possible to use Model.create inside a begin/rescue block
  and get access to the underlying instance if there is a validation
  or before/around hook error.

* The subclasses plugin now accepts a block, which is called with
  each model class created.  This is useful if you want to apply
  changes to classes created in the future instead of just existing
  classes.

* The validates_unique validation in the validation_helpers plugin
  now accepts a :where option for a custom uniqueness filter.  Among
  other things this makes it easy to implement a case insensitive
  uniqueness validation on a case sensitive column.

* The threaded connection pools now support a
  :connection_handling=>:disconnect option, which makes them disconnect
  connections after use instead of returning them to the pool.  This
  makes it possible to completely control connection lifetime using
  Database#synchronize.

* The pg_row_op extension now has support for PGRowOp#*, for referencing
  the members of the composite type as separate columns.

* MySQL's set type and default value are now recognized.

* bin/sequel now accepts a -c argument for running an arbitrary
  code string instead of using an IRB prompt.

= Other Improvements

* Sequel now parses current date/timestamp column defaults when
  parsing the schema for a table.  The values will be returned
  as Sequel::CURRENT_DATE for date columns and
  Sequel::CURRENT_TIMESTAMP for timestamp columns.

  The schema_dumper extension will work with these defaults, so
  if you dump the schema for a table with a column that uses
  a current timestamp default, the dumped schema will include
  the default.

  The defaults setter plugin also works with these changes, so
  that when new model objects are instantiated, they get the
  current Date/Time/DateTime values set.

* On MySQL and PostgreSQL, Sequel will now by default attempt
  to combine multiple alter_table operations into a single
  query where it believes it can do so correctly.  This can
  potentially improve performance ~N times, where N is the number
  of alter table operations.

  This can change the SQL used for old migrations (though it
  shouldn't change the result), and is a potentially risky
  change.  This may be disabled by default in future versions
  if it causes problems.

* The defaults_setter plugin now correctly sets false default
  values.

* The schema_dumper plugin now preserves fractional seconds
  in timestamp column defaults when dumping.

* Time->DateTime and DateTime->Time typecasts now retain
  fractional seconds on ruby 1.8.

* Array arguments passed to most PGArrayOp methods are now
  automatically wrapped in a PGArray.  If you want to use this
  support, you need to make sure to load both the pg_array
  and pg_array_op extensions.

* Sequel now does a better job of finding the sequence for a
  given table on PostgreSQL, handling more corner cases.  A small
  side effect of this is sometimes sequence names will be quoted.

* Some potential thread-safety issues when using Sequel with
  PostgreSQL on a non-GVL ruby implementation have been fixed.

* Sequel now correctly caches the server version query on MySQL.

* Sets of alter_table operations on MySQL and Microsoft SQL Server
  that require parsing the current database schema, where later
  alter_table operations depend on earlier ones, should now work
  correctly.

* You can now drop check constraints on tables on SQLite, though
  doing so drops all check constraints on the table, not only the
  specific check constraint given.

* The identity_map plugin no longer breaks if used with a model
  without a primary key.

* Sequel::SQL::NegativeBooleanConstant now inherits from Constant
  instead of BooleanConstant.  This means that

    Sequel::NULL == Sequel::NOTNULL

  is now false instead of true.

* You can now override the convert_tinyint_to_bool settings on a
  per-Dataset basis in the mysql and mysql2 adapters, though
  the overriding is different depending on the adapter.  Check the
  commit log for details.

* timestamp(N) types are now recognized as datetime, which should
  fix certain cases on Oracle.

* Dataset#insert now handles a single model instance argument
  as a single value if the model uses the pg_row plugin.

* When joining a model dataset using a model class as the table
  argument, a subselect is used unless the model is a simple select
  from the underlying table.

* The specs now cleanup after themselves, dropping the tables that
  they create for testing.

= Backwards Compatibility

* The defaults_setter plugin's behavior changed due to the 
  current date/timestamp support.  Previously, it would not set
  a value for the column, since the default wasn't recognized.
  Therefore, the database would use the default value on insert,
  which would be the database's current timestamp.

  Now, the value is set to the current Date/Time/DateTime on
  model object instantiation, so the database wouldn't use the
  column default.  Instead of the database's current timestamp
  on insert, the column value will be the application's
  current timestamp on model instantiation.

  Users who don't want this behavior can remove the default values
  in the model:

    Model.default_values.delete(:column_name)

* Plain (non-model) datasets no longer allow insert to accept
  a single model instance argument.  Also, they no longer call
  values on a single argument if the object responds to it.

* Plain (non-model) datasets no longer accept model classes as
  tables in the join/graph methods.  Also, they no longer call
  table_name on the argument if the object responds to it.

* The schema_dumper extension now requires the eval_inspect
  extension, which changes inspect output for
  Sequel::SQL::Expression objects.

* Custom adapters that override Database#alter_table_sql_list now
  need to make sure it returns an already flattened array.

* The identity_map_key method in the identity_map plugin now returns
  nil instead of a random string if the given pk is nil.

---

### Doc Release Notes 3.4.0 (`doc/release_notes/3.4.0.txt`)

New Plugins
-----------

* A nested_attributes plugin was added allowing you to modify
  associated objects directly through a model object, similar to
  ActiveRecord's Nested Attributes.
  
    Artist.plugin :nested_attributes
    Artist.one_to_many :albums
    Artist.nested_attributes :albums
    a = Artist.new(:name=>'YJM',
     :albums_attributes=>[{:name=>'RF'}, {:name=>'MO'}])
    # No database activity yet

    a.save # Saves artist and both albums
    a.albums.map{|x| x.name} # ['RF', 'MO']
  
  It takes most of the same options as ActiveRecord, as well as a
  a few additional options:
  
  * :destroy - Allow destruction of nested records.
  * :limit - For *_to_many associations, a limit on the number of
    records that will be processed, to prevent denial of service
    attacks.
  * :remove - Allow disassociation of nested records (can remove the
    associated object from the parent object, but not destroy the
    associated object).
  * :strict - Set to false to not raise an error message if a primary
    key is provided in a record, but it doesn't match an existing
    associated object.
    
  If a block is provided, it is passed each nested attribute hash.
  If the hash should be ignored, the block should return anything
  except false or nil.

* A timestamps plugin was added for automatically adding
  before_create and before_update hooks for setting values on
  timestamp columns.  There are a couple of existing external
  plugins that handle timestamps, but the implementations are
  suboptimal.  The new built-in plugin supports the following
  options (with the default in parentheses):
  
  * :create - The field to hold the create timestamp (:created_at)
  * :force - Whether to overwrite an existing create timestamp
    (false)
  * :update - The field to hold the update timestamp (:updated_at)
  * :update_on_create - Whether to set the update timestamp to the
    create timestamp when creating (false)
      
* An instance_hooks plugin was added for adding hooks to specific
  w
  model instances:
  
    obj = Model.new
    obj.after_save_hook{do_something}
    obj.save # calls do_something after the obj has been saved

  All of the standard hooks are supported, except for
  after_initialize.  Instance level before hooks are executed in
  reverse order of addition before calling super.  Instance level
  after hooks are executed in order of addition after calling super.
  If any of the instance level before hook blocks return false, no
  more instance level before hooks are called and false is returned.

  Instance level hooks are cleared when the object is saved
  successfully.
  
* A boolean_readers plugin was added for creating attribute? methods
  for boolean columns.  This can provide a nicer API:
  
    obj = Model[1]
    obj.active  # Sequel default column reader
    obj.active? # Using the boolean_readers plugin
    
  You can provide a block when loading the plugin to change the
  criteria used to determine if the column is boolean:
  
    Sequel::Model.plugin(:boolean_readers) do |c|
      db_schema[c][:db_type] =~ /\Atinyint/
    end
    
  This may be useful if you are using MySQL and have some tinyint
  columns that represent booleans and others that represent integers.
  You can turn the convert_tinyint_to_bool setting off and use the
  attribute methods for the integer value and the attribute? methods
  for the boolean value.

Other New Features
------------------

* Sequel now has support for converting Time/DateTime to local or UTC
  time upon storage, retrieval, or typecasting.
  
  There are three different timezone settings:

  * Sequel.database_timezone - The timezone that timestamps use in
    the database.  If the database returns a time without an offset,
    it is assumed to be in this timezone.

  * Sequel.typecast_timezone - Similar to database_timezone, but used
    for typecasting data from a source other than the database.  This
    is currently only used by the model typecasting code.

  * Sequel.application_timezone - The timezone that the application
    wants to deal with.  All Time/DateTime objects are converted into
    this timezone upon retrieval from the database.

  Unlike most things in Sequel, these are only global settings, you
  cannot change them per database.  There are only three valid
  timezone settings:

  * nil (the default) - Don't do any timezone conversion.  This is
    the historical behavior.

  * :local - Convert to local time/Consider time to be in local time.

  * :utc - Convert to UTC/Consider time to be in UTC.

  So if you want to store times in the database as UTC, but deal with
  them in local time in the application:

    Sequel.application_timezone = :local
    Sequel.database_timezone = :utc

  If you want to set all three timezones to the same value:

    Sequel.default_timezone = :utc

  There are three conversion methods that are called:

  * Sequel.database_to_application_timestamp - Called on time objects
    coming out of the database.  If the object coming out of the
    database (usually a string) does not have an offset, assume it is
    already in the database_timezone.  Return a Time/DateTime object
    (depending on Sequel.datetime_class), in the application_timezone.

  * Sequel.application_to_database_timestamp - Used when literalizing
    Time/DateTime objects into an SQL string.  Converts the object to
    the database_timezone before literalizing them.

  * Sequel.typecast_to_application_timestamp - Called when
    typecasting objects for model datetime columns.  If the object
    being typecasted does not already have an offset, assume it is
    already in the typecast_timezone.  Return a Time/DateTime object
    (depending on Sequel.datetime_class), in the
    application_timezone.

  Sequel does not yet support named timezones or per thread
  modification of the timezone (for showing all timestamps in the
  current user's timezone).  Extensions to support both features are
  planned for a future version.

* Dataset#truncate was added for truncating tables.  Truncate allows
  for fast removal of all rows in a table.
  
* Sequel now supports typecasting a hash to date, time, and datetime
  types.  This allows easy usage of Sequel with forms that split
  the entry of these database types into separate from fields.
  With this code, you can just have field names like:

    date[year]
    date[month]
    date[day]

  Rack will parse that into:

    {'date'=>{'year'=>?, 'month'=>?, 'day'=>?}}

  So then you can do:

    obj.date = params['date']
    # or
    obj.set(params)
  
* validates_unique now takes a block that can be used to scope the
  uniqueness constraint. This allows you to easily set up uniqueness
  validations that are only necessary in a given scope.  For example,
  a validation on username, but only for active users (as inactive
  users are soft deleted but remain in the table).  You just pass a
  block to validates_unique:

    validates_unique(:name){|ds| ds.filter(:active)}
    
* The serialization plugin now supports json.
    
* Sequel now supports generic concepts of
  CURRENT_{DATE,TIME,TIMESTAMP}.  Most databases support these SQL
  concepts, but not all, and some implementations act differently.

  The Sequel::SQL::Constants module holds the three constants,
  which are instances of SQL::Constant, an SQL::GenericExpression
  subclass.  This module is included in Sequel, so you can reference
  the constants more easily (e.g. Sequel::CURRENT_TIMESTAMP).
  It's separated out into a separate module so that you can just
  include that module in the top level scope, allowing you to
  reference the constants directly (e.g. CURRENT_TIMESTAMP).
  
    DB[:events].filter{date < ::Sequel::CURRENT_DATE}
    # or:
    include Sequel::SQL::Constants
    DB[:events].filter{date < ::CURRENT_DATE}

* Database#run was added for executing arbitrary SQL on a database.
  It's an alias for Database#<<, but it allows for a nicer API inside
  migrations, since you can now do:
  
    run 'SQL'
    
  instead of:
  
    self << 'SQL'
    
  You can also provide a :server option to run the SQL on the
  given server/shard:
  
    run 'SQL', :server=>:shard1

* Sequel::Model() can now take a database argument in addition to
  a symbol or dataset argument.  If a database is given, it'll create
  an anonymous subclass attached to the given database.  Other changes
  were made to allow the following code to work:
  
    class Item < Sequel::Model(DB2)
    end
    
  That will work correctly assuming a table named items in DB2.

* Dataset#ungrouped was added for removing a grouping from an
  existing dataset.  Also, Dataset#group when called with no arguments
  or with a nil argument also removes any existing grouping instead
  of resulting in invalid SQL.

* Model#modified? was added, letting you know if the model has been
  modified.  If the model hasn't been modified, calling
  Model#save_changes will do nothing.

* SQL::OrderedExpression now supports #asc, #desc, and #invert.

Other Improvements
------------------

* The serialization and lazy_attribute plugins now add accessor
  methods to a module included in the class, instead of to the
  model class itself.  This allows the methods to be overridden
  in the class and work well with super, as well for the plugins
  to work together on the same column.  Make sure the
  lazy_attributes accessor is setup before the serialization
  accessor if you want to have a lazy serialized column.
  
* Calling the add_* method for many_to_many association now saves the
  record if the record is new.  This makes it operate more similarly
  to one_to_many associations.  Previously, it raised an Error.

* Dataset#import now works correctly when called with a dataset.
  Previously, it generated incorrect SQL.

* The JDBC adapter now converts byte arrays to/from SQL::Blob.

* The JDBC adapter now attempts to bind unknown types using
  setObject instead of raising, so it can work with native Java
  objects.  It also binds boolean parameters correctly.

* Using multiple emulated ALTER TABLE statements (such as
  drop_column) in a single alter_table block now works correctly
  on SQLite.
  
* Database#indexes now works on JDBC for tables in a non-default
  schema.  It also now properly detects unique indexes on MSSQL.

* Database#schema on JDBC now accepts a :schema option.  Also,
  returned schema hashes now include a :column_size entry specifying
  the maximum length/precision for the column, since the
  :db_type entry doesn't have contain the information on JDBC.

* Datasets without tables now work correctly on Oracle, so things
  like DB.get(...) now work.
  
* A descriptive error message is given if you attempt to use
  Sequel with the mysql.rb driver (which Sequel doesn't support).
  
* The postgres adapter now works correctly with a modified
  postgres-pr that raises PGErrors instead of RuntimeErrors
  (e.g. http://github.com/jeremyevans/postgres-pr).
  
* You now get a Sequel::InvalidOperation instead of a NoMethodError
  if you attempt to update a dataset without a table.
  
* The inflection support has been modified to reduce code
  duplication.

Backwards Compatibility
-----------------------

* Sequel now includes fractional seconds in timestamps for all
  adapters except MySQL.  It's possible that this may break
  timestamp columns for databases that are not regularly tested.
  
* Sequel now includes timezone values in timestamps on Microsoft
  SQL Server, Oracle, PostgreSQL and SQLite.  The modification for
  SQLite is probably the biggest cause for concern, since SQLite
  stores times as text.  If you have an SQLite database that uses
  timestamps and is accessed by something other than Sequel, you
  should make sure that it works with the timestamp format that
  Sequel now uses.
  
* The default timestamp format used by Sequel now uses a space
  instead of 'T' between the date and time parts, which could
  possibly affect some databases that are not regularly tested.

* Attempting to insert into a grouped dataset or a dataset that
  selects from multiple tables will now raise an Error.  Previously,
  it would ignore any GROUP or JOIN settings and generate bad SQL if
  there were multiple FROM tables.
  
* Database#<< now always returns nil.  Before, the return value was
  adapter dependent.

* ODBC::Time and ODBC::DateTime values are now converted to the
  Sequel.datetime_class.  Before, ODBC::Time used Time and
  ODBC::DateTime used DateTime regardless of the
  Sequel.datetime_class setting.
  
* The default inflections were modified, fixing some obvious errors
  and possibly changing some existing inflections.  Further changes
  to the default inflections are unlikely.

---

### Doc Release Notes 3.40.0 (`doc/release_notes/3.40.0.txt`)

= New Features

* Sequel now has vastly improved support for Microsoft Access.

* Sequel now supports the CUBRID database, with a cubrid adapter
  that uses the cubrid gem, and a jdbc/cubrid adapter for accessing
  CUBRID via JDBC on JRuby.

* The association_pks plugin now supports composite keys.

* Database#transaction now accepts a :disconnect=>:retry option,
  in which case it will automatically retry the block if it
  detects a disconnection.  This is potentially dangerous, and
  should only be used if the entire block is idempotent.  There
  is also no checking against an infinite retry loop.

* SQL::CaseExpression#with_merged_expression has been added, for
  converting a CaseExpression with an associated expression to
  one without an associated expression, by merging the expression
  into each condition.

= Other Improvements

* Sequel now quotes arguments/columns in common table expressions.

* Sequel now handles nil values correctly in the pg_row extension.

* Sequel::Postgres::HStore instances can now be marshalled.

* Sequel now uses clob for String :text=>true types on databases that
  don't support a text type.

* On PostgreSQL, Sequel now quotes channel identifier names when using
  LISTEN/NOTIFY.

* On PostgreSQL, Sequel now correctly handles the case where named
  type conversion procs have been added before the Database object is
  instantiated.

* On DB2, Sequel now explicitly sets NOT NULL for unique constraint
  columns instead of foreign key columns.  DB2 does not allow columns
  in unique constraints to be NULL, but does allow foreign key columns
  to be NULL.

* In the oracle adapter, clob values are now returned as ruby strings
  upon retrieval.

* Sequel now detects more types of disconnections in the postgres,
  mysql, and mysql2 adapters.

* If a database provides a default column value that isn't a ruby
  string, it is used directly as the ruby default, instead of causing
  the schema parsing to fail.

= Backwards Compatibility

* Code using Sequel's oracle adapter that expected clob values to be
  returned as OCI8::CLOB instances needs to be modified to work with
  ruby strings.

* Because Sequel now quotes column names in common table expressions,
  those names are now case sensitive, which could break certain poorly
  coded queries.  Similar issues exist with the quoting of channel
  identifier names in LISTEN/NOTIFY on PostgreSQL.

* The private Database#requires_return_generated_keys? method
  has been removed from the jdbc adapter.  Custom jdbc subadapters
  relying on this method should override the private
  Database#execute_statement_insert method instead to ensure that
  RETURN_GENERATED_KEYS is used for insert statements.

* The private Dataset#argument_list and #argument_list_append methods
  have been removed.

---

### Doc Release Notes 3.41.0 (`doc/release_notes/3.41.0.txt`)

= New Features

* A connection_validator extension has been added, which
  automatically determines if connections checked out from the pool
  are still valid.  If they are not valid, the connection is
  disconnected and another connection is used automatically,
  transparent to user code.

  Checking if connections are valid requires a query, so this
  extension causes a performance hit.  For that reason, connections
  are only checked by default if they have been inactive for more than
  a configured amount of time (1 hour by default).  You can choose to
  validate connections on every checkout via:

    DB.pool.connection_validation_timeout = -1

  However, this can cause a substantial performance hit unless you are
  purposely using coarse connection checkouts via manual calls to
  Database#synchronize (for example, in a Rack middleware).  Using
  coarse checkouts can greatly reduce the amount of concurrency that
  Sequel supports (for example, limiting the number of concurrent
  requests to the number of database connections), so this method is
  not without its tradeoffs.

* Sequel.delay has been added for a generic form of delayed
  evaluation.  This method takes a block and delays evaluating it
  until query literalization.  By default, Sequel evaluates most
  arguments immediately:

    foo = 1
    ds = DB[:bar].where(:baz=>foo)
    # SELECT * FROM bar WHERE (baz = 1)
    foo = 2
    ds
    # SELECT * FROM bar WHERE (baz = 1)

  Using Sequel.delay, you can delay the evaluation:

    foo = 1
    ds = DB[:bar].where(:baz=>Sequel.delay{foo})
    # SELECT * FROM bar WHERE (baz = 1)
    foo = 2
    ds
    # SELECT * FROM bar WHERE (baz = 2)

* Sequel now supports the :unlogged option when creating tables on
  PostgreSQL, to create an UNLOGGED table.

* On SQLite, Database#transaction now supports a :mode option for
  setting up IMMEDIATE/EXCLUSIVE SQLite transactions.  Sequel also
  supports a Database#transaction_mode accessor for setting the
  default transaction mode on SQLite.

* Most pg_* extension objects (e.g. PGArray) now support the #as
  method for creating an SQL::AliasedExpression object.

* The single_table_inheritance plugin now supports non-bijective
  mappings.  In lay terms, this means that a one-to-one mapping
  of column values to classes is no longer required.  You can now
  have multiple column values that map to a single class in the
  :model_map option, and specify a :key_chooser option to choose
  which column value to use for the given model class.

* The touch plugin now handles the touching of many_to_many
  associations, and other associations that use joined datasets.

* ConnectionPool#pool_type has been added. It returns a symbol
  representing the type of connection pool in use (similar to
  Database#database_type).

* Database#valid_connection? has been added for checking if a given
  connection is still valid.

* Database#disconnect_connection is now part of the public API, and
  can be used to disconnect a given connection.

= Other Improvements

* Uniqueness validation now correctly handles nil values.
  Previously, it checked the underlying table for other rows where
  the column IS NULL, but that is incorrect behavior.  Sequel's new
  (correct) behavior is to skip the uniqueness check if the column
  is nil.

* Foreign key parsing is now supported on Microsoft SQL Server.

* Dataset#reverse and #reverse_order now accept virtual row blocks.

* Changing the name of the primary key column, and possibly other
  schema changes on the primary key column, are now supported on
  MySQL.

* Primary key columns are now specifically marked as NOT NULL on
  SQLite, as non-integer primary keys on SQLite are not considered
  NOT NULL by default.

* Failure to create a native prepared statement is now handled
  better in the postgres, mysql, and mysql2 adapters.

* Firebird now emulates selecting data without an underlying table
  (e.g. DB.get(1)).

* Finding the name of the constraint that sets column defaults on
  Microsoft SQL Server now works correctly on JRuby 1.7.

* An additional type of disconnect error is now recognized in the
  jdbc/sqlserver adapter.

* Many adapters have been fixed so that they don't raise an exception
  if trying to disconnect an already disconnected connection.

* Many adapters have been fixed so that
  Database#log_connection_execute logs and executes the given SQL
  on the connection.

* Many adapters have been fixed so that
  Database#database_error_classes returns an array of database
  exception classes for that adapter.

* Database#log_exception now handles a nil exception message.

* Dataset#limit(nil, nil) now resets offset in addition to limit, but
  you should still use Dataset#unlimited instead.

* A bin/sequel usage quide has been added to the documentation.

= Backwards Compatibility

* Sequel now treats clob columns as strings instead of blobs
  (except on DB2 when use_clob_as_blob = true).  This can make it
  so the values are returned as strings instead of SQL::Blob values.
  Since SQL::Blob is a String subclass, this generally will
  not affect user code unless you are passing the values as input
  to a separate blob column.

* The Database <-> ConnectionPool interface was completely changed.
  Sequel no longer supports custom connection procs or disconnection
  procs in the connection pools.  The :disconnection_proc Database
  option is no longer respected, and blocks passed to Database.new
  are now ignored.

  This change should not be user-visible, but if you had any code
  that was monkeying with the connection pool internals, you may
  need to modify it.

* Code that was using the uniqueness check to also check for presence
  should add a separate check for presence.  Such code was broken,
  as it only worked if there was already a NULL column value in the
  table. If you were relying on this broken behavior, you should
  clean up the NULL data in the column and then mark the database
  column as NOT NULL.

* If you have code that specifically abuses the fact that non-integer
  primary keys on SQLite allow NULL values by default, it will no
  longer work.

---

### Doc Release Notes 3.42.0 (`doc/release_notes/3.42.0.txt`)

= New Features

* Dataset#avg, #interval, #min, #max, #range, and #sum now
  accept virtual row blocks, allowing you to more easily get
  aggregate values of expressions based on the table:

    DB[:table].sum{some_function(column1, column2)} # => 134
    # SELECT sum(some_function(column1, column2)) FROM table

* Database#do has been added on PostgreSQL for using the DO
  anonymous code block execution statement.

* Model.dataset_module now uses a Module subclass, which allows
  you to call subset inside a dataset_module block, making
  it easier to consolidate dataset method code:

    class Album < Sequel::Model
      dataset_module do
        subset(:gold){copies_sold > 500000}
      end
    end

* Database#copy_table and #copy_into are now supported on
  jdbc/postgres.

* Sequel now supports deferred constraints on constraint types other
  than foreign keys.  The only databases that appear to implement
  this are Oracle and PostgreSQL.

* Sequel now supports INITIALLY IMMEDIATE deferred constraints via
  the :deferrable=>:immediate constraint/column option.

* Sequel now supports setting the default size of string columns,
  via the default_string_column_size option or accessor.  In some
  cases, Sequel's default string column size of 255 is too large
  (e.g. MySQL with utf8mb4 character set), and this allows you to
  change it.

= Other Improvements

* Dataset#count and other methods now use a subselect in the case
  where the dataset has an offset but no limit.

* If an error occurs while attempting to commit a transaction, Sequel
  now attempts to rollback the transaction.  Some databases do this
  automatically, but not all.  Among other things, this fixes issues
  with deferred foreign key constraint violations on SQLite.

* When extending a model's dataset, the model's instance_dataset is
  reset, insuring that it will also be extended with the module.

* When passing an invalid argument to Dataset#filter, the exception
  message now includes the argument.

* The force_encoding plugin now works with frozen string values.

* Public methods added to a model dataset_module now have model
  class methods created for them even if the method was added outside
  of a dataset_module block.

* On PostgreSQL, Database#indexes now includes a :deferrable entry
  for each index hash, which will be true for unique indexes where
  the underlying constraint is deferrable.

* On Microsoft SQL Server 2000, Dataset#update no longer includes a
  limit (TOP), allowing it to work correctly. 

= Backwards Compatibility

* Model.dataset_methods has been removed.  This was used to store
  blocks for methods created via def_dataset_method and subset.
  The internals have been changed so that a dataset_module is
  always used in these cases, therefore there was no longer a reason
  for this method.

---

### Doc Release Notes 3.43.0 (`doc/release_notes/3.43.0.txt`)

= New Features

* A core_refinements extension has been added, which offers
  refinement versions of Sequel's core extensions.  This requires
  the new experimental refinement support added in ruby 2.0, and
  allows you to use the Sequel DSL methods in a file without
  actually modifying the Symbol, String, Array, and Hash classes.

* A date_arithmetic extension has been added for performing
  database-independent date calculations (adding/subtracting an
  interval to/from a date):

    Sequel.extension :date_arithmetic
    e = Sequel.date_add(:date_column, :years=>1, :months=>2, :days=>3)
    DB[:table].where(e > Sequel::CURRENT_DATE)

  In addition to providing the interval as a hash, you can also
  provide it as an ActiveSupport::Duration object.  This extension
  is supported on 11 database types.

* Dataset#get can now take an array of multiple expressions to get
  an array of values, similar to map/select_map:

    value1, value2 = DB[:table].get([:column1, :column2])

* Sequel can now handle [host.]database.schema.table qualified
  tables on Microsoft SQL Server.  To implement this support,
  the split_qualifiers method has been added to Database and
  Dataset for taking a possibly qualified identifier and splitting
  it into an array of identifier strings.

* The string_stripper plugin now offers the ability to manually
  specify which columns to skip stripping for via
  Model.skip_string_stripping. 

= Other Improvements

* The jdbc adapter now works with the new jdbc-* gems, which require
  a manual load_driver step that the older jdbc-* gems did not
  require.

* The string_stripper plugin no longer strips blob columns or values.

* Database#copy_into in both the postgres and jdbc/postgres adapters
  has been fixed to better handle exceptions.  

* Dataset#hash and Model#hash are now significantly faster.

* Lambda procs with 0 arity can now be used as virtual row blocks
  on ruby 1.9.  Previously, attempting to use a lambda proc with
  0 arity as a virtual row block on ruby 1.9 would raise an exception.

* Schema-qualified composite types are now handled correctly in
  the pg_row extension.

* Database#reset_primary_key_sequence on PostgreSQL now works
  correctly when a default_schema is set.

* tinyint(1) unsigned columns on MySQL are now parsed as booleans
  instead of integers on MySQL if converting tinyint to boolean.
   
* The jdbc adapter now supports the jdbc-hsqldb gem, so you can
  now install that instead of having to require the .jar manually.

* Blobs are now casted correctly on DB2 when the use_clob_as_blob
  setting is false.

* Oracle timestamptz types are now handled correctly in the
  jdbc/oracle adapter.

* Sequel now defaults to :prefetch_rows = 100 in the oracle
  adapter, which can significantly improve performance.

* Sequel now defines respond_to_missing? where method_missing? is
  defined and the object also responds to respond_to?.

* Sequel::BasicObject now responds to instance_exec on ruby 1.8.

= Backwards Compatibility

* The meta_def method that was defined on Database, Dataset, and
  Model classes and instances has been moved to an extension named
  meta_def, and is no longer loaded by default.  This method was
  previously used internally, and it wasn't designed for external
  use.  If you have code that uses meta_def, you should now load the
  extension manually:

    Sequel.extension :meta_def

* The private _*_dataset_helper model association methods are no
  longer defined.  The AssociationReflection#dataset_helper_method
  public method is also no longer defined.

* Dataset#schema_and_table now always returns strings (or nil).
  Before, in some cases it would return symbols.

* Using a conditions specifier array with Dataset#get no longer
  works due to the new multiple values support in Database#get.
  So code such as:

    DB[:table].get([[:a, 1], [:b, 2]])

  should be changed to:

    DB[:table].get(Sequel.expr([[:a, 1], [:b, 2]]))

---

### Doc Release Notes 3.44.0 (`doc/release_notes/3.44.0.txt`)

= New Features

* Dataset#paged_each has been added, for processing entire datasets
  without keeping all rows in memory, even if the underlying driver
  keeps all query results in memory.  This is implemented using
  limits and offsets, and requires an order (model datasets use a
  default order by primary key).  It defaults to fetching 1000
  rows at a time, but that can be changed via the :rows_per_fetch
  option.

  This method is drop-in compatible for each.  Previously, the
  pagination extension's each_page method could be used for a
  similar purpose, but users of each_page are now encouraged to
  switch to paged_each.

* Sequel now recognizes constraint violation exceptions on most
  databases, and will raise specific exceptions for different
  types of constraint violations, instead of the generic
  Sequel::DatabaseError:

  * Sequel::ConstraintViolation (generic superclass)
  * Sequel::CheckConstraintViolation
  * Sequel::NotNullConstraintViolation
  * Sequel::ForeignKeyConstraintViolation
  * Sequel::UniqueConstraintViolation
  * Sequel::Postgres::ExclusionConstraintViolation

* The :dataset association option can now take accept an optional
  association reflection option.  Instead of doing:

    Album.one_to_many :artists,
      :dataset=>{Artist...}

  you can now do:

    Album.one_to_many :artists,
      :dataset=>{|r| r.associated_dataset...}

  This second form will perform better.

* Temporary views are now supported on PostgreSQL and SQLite using
  the :temp option to create_view.

= Other Improvements

* Row fetching speed in the tinytds adapter has been increased by
  up to 60%.

* Row fetching speed in the mysql2 adapter when using an identifier
  output method has been increased by up to 50%.

* On databases where offsets are emulated via the ROW_NUMBER window
  function (Oracle, DB2, Microsoft SQL Server), using an offset in
  a subselect is now supported.  For example, the following code
  previously didn't work correctly with emulated offsets:

    # Second 5 rows ordered by column2 of the second 10 rows ordered
    # by column 1.
    DB[:table].order(:column1).limit(10, 10).
      from_self.order(:column2).limit(5, 5)

  Row processing speed has been increased slightly for all adapters
  that supported databases where offsets are emulated.

* Association method performance has improved by caching an
  intermediate dataset.  This can close to triple the performance
  of the association_dataset method, and increase the performance
  of the association method by close to 30%.

* Virtual Row performance has increased about 30% in the typical
  case by using a shared VirtualRow instance.

* Database#create_or_replace_view is now emulated on databases that
  don't support it directly by dropping the view before attempting
  to create it.

* The columns_introspection extension can now introspect for simple
  select * queries from subselects, and it can now use the cached
  schema information in the database for simple select * queries
  from tables.

* The identity_map plugin now works correctly with many-to-many
  right-side composite keys.

* Dataset#last for Model datasets now works even if you don't specify
  an order explicitly, giving the last entry by primary key.  Note
  that Dataset#first for model datasets still does not order by
  default.

* The eager_each plugin no longer uses Object#extend at runtime.

* Database#remove_cached_schema is now thread-safe on non-GVL ruby
  implementations.

* Connection errors in the jdbc adapter now provide slightly more
  helpful messages.

* Sequel now uses the standard offset emulation code in the
  jdbc/as400 adapter, instead of custom offset emulation code
  specific to that adapter.

* Database#create_view with a dataset now works correctly when using
  the pg_auto_parameterize extension.

* Database#columns no longer calls the row_proc.

* Dataset#schema_and_table no longer turns a literal string into a
  non-literal string.

* The oracle adapter now works with a :prefetch_rows=>nil option,
  which explicitly disables prefetching.

* The mock mssql adapter now sets a server_version so that more
  parts of it work.

= Backwards Compatibility

* Offset emulation via ROW_NUMBER works by moving the query to a
  subselect that also selects from the ROW_NUMBER window function,
  and filtering on the ROW_NUMBER in the main query.  Previously, the
  ROW_NUMBER was also present in the output columns, and some
  adapter code was needed to hide that fact.  Now, the outer select
  selects all of the inner columns in the subselect except for the
  ROW_NUMBER, reducing the adapter code needed. This has the side
  effect of potentially requiring a query (or multiple queries for
  multiple subselects) to determine the columns to use.  The
  columns_introspection extension may reduce the number of queries
  needed.

* The correlated_subquery eager limit strategy is no longer supported
  on Microsoft SQL Server for many_*_many associations.  As the
  window_function eager limit strategy is supported there, there is
  no reason to use the correlated_subquery strategy.

* The public AssociationReflection#_dataset_method method has been
  removed.

* The private _*_dataset methods for associations (e.g.
  _albums_dataset) have been removed.

* The private Dataset#offset_returns_row_number_column? method has
  been removed.

* :conditions options for associations are now added to the
  association dataset before the foreign key filters, instead of
  after.  This should have no effect unless you were introspecting
  the dataset's opts or sql and acting on it.

* The added abilities in the columns_introspection plugin to use
  cached schema for introspection can now cause it to return
  incorrect results if the table's schema has changed since it was
  cached by Sequel.

---

### Doc Release Notes 3.45.0 (`doc/release_notes/3.45.0.txt`)

= New Features

* Database#transaction now recognizes a :retry_on option, which
  should contain an exception class or array of exception classes.
  If the transaction raises one of the given exceptions, Sequel
  will automatically retry the transaction block.  It's a bad idea to
  use this option if the transaction block is not idempotent.

  By default, Sequel only retries the block 5 times by default,
  to protect against infinite looping.  You can change the number
  of retries with the :num_retries option.

  Users of the :disconnect=>:retry option are encouraged to switch
  to :retry_on=>Sequel::DatabaseDisconnectError.

* Dataset#escape_like has been added for escaping LIKE
  metacharacters.  This is designed for the case where part of
  the LIKE pattern is based on user input that should not treat the
  metacharacters specially.

* Serialization failures/deadlocks are now raised as
  Sequel::SerializationFailure exception instances.  This exception
  class is a good candidate for the transaction :retry_on option.

* On PostgreSQL, you can now provide the :force_standard_strings
  and :client_min_messages Database options to override the defaults
  on a per-instance basis.

* On PostgreSQL, Database#tables and #views now recognizes a
  :qualify option, which if true will return qualified identifiers
  instead of plain symbols.

* Transaction isolation levels are now supported on Oracle, DB2,
  and all jdbc subadapters using the JDBC transaction support.

* Dataset.def_mutation_method now accepts a :module option for
  the module in which to define the methods (defaulting to self).

* An unlimited_update plugin has been added.  It's sole purpose is to
  eliminate a MySQL warning in replicated environments, since by
  default Sequel::Model uses a LIMIT clause when updating on MySQL.

* The named_timezones extension now adds a
  Sequel.tzinfo_disambiguator accessor to automatically handle
  TZInfo::AmbiguousTime exceptions.  This should be a callable object
  that accepts two arguments, a DateTime instance and an array of
  timezone periods, and returns the timezone period to use.

= Other Improvements

* Sequel now handles JSON securely, specifying the
  :create_additions=>false option when using JSON.parse.  If you
  really want to get the old vulnerable behavior back, override
  Sequel.parse_json.

* The json_serializer and xml_serializer plugins are now secure
  by default.  Before, the default behavior of these plugins
  allowed for round tripping, such that:

    Album.from_xml(album.to_xml) == album

  Unfortunately, that requires that the deserialization allow
  the setting of any column.  Since the plugins also handle
  associations, you could also set any column in any associated
  object, even cascading to associated objects of those objects.

  The new default behavior only allows deserialization to set
  the same columns that mass-assignment would set, and not to
  handle associated objects at all by default.  The following
  additional options are supported:

    :fields :: The specific fields to set (this was already supported
               by the json_serializer plugin).
    :associations :: The specific associations to handle.
    :all_columns :: The previous behavior of setting all columns.
    :all_associations :: The previous behavior of setting all
                         associations.

  Since JSON parsing no longer deserializes into arbitrary ruby
  instances, from_json and array_from_json class methods have been
  added to the json_serializer plugin, for deserializing into model
  instances.  These mirror the from_xml and array_from_xml class
  methods in the xml_serializer plugin.

  Note that the :all_columns and :all_associations methods were
  only added to make backwards compatibility easier.  It is
  likely they will be removed in Sequel 4, along with the
  json_create class method.

* Sequel now attempts to use database specific error codes or
  SQLState codes instead of regexp parsing to determine if a more
  specific DatabaseError subclass should be used.  This should make
  error handling faster and more robust.

* Sequel now uses ESCAPE '\' when using LIKE, for similar behavior
  across databases.  Previously, no ESCAPE clause was used, so
  behavior differed across databases, with most not using escaping,
  and PostgreSQL, MySQL, and H2 defaulting to backslash as the escape
  character.

* The query extension has been reimplemented and now uses a proxy
  object instead of Object#extend.

* The :pool_timeout Database option now supports fractional seconds.

* Database#quote_identifier is now a public method.

* Metadata parsing (schema, indexes, foreign_key_list) on PostgreSQL
  now correctly handles the case where an unqualified table name is
  used and tables with that name exist in multiple schemas.  It now
  picks the first matching table in the schema_search_path, instead of
  failing or returning results from all tables.

* Sequel::Model instances no longer attempt to typecast the money
  type on PostgreSQL, since the previous typecast didn't work
  correctly, and correct typecasting is locale-dependent.

* Sequel no longer picks up foreign keys for tables in other
  databases when using Database#foreign_key_list on MySQL.

* A warning when using the mysql2 3.12 beta has been eliminated.

* A warning has been eliminated when using the jdbc/oracle adapter
  on JRuby 1.7.

* Sequel's ilike emulation should now work by default on databases
  without specific syntax support.

* Dataset#from_self! no longer creates a self referential dataset.

* Coverage testing now uses simplecov instead of rcov on ruby 1.9+.

= Backwards Compatibility

* The switch to using JSON.parse :create_additions=>false means
  that if your app expected JSON to deserialize into arbitrary
  ruby objects, it is probably broken.  You should update your
  application code to manually convert the deserialized hashes
  into the ruby objects you want.

  Note that it's not just this new version of Sequel that will
  cause that, older versions of Sequel will break in the same
  way if you update your JSON library to a version that is not
  vulnerable by default.

  This potentially affects the pg_json extension and serialization
  plugin if you were expecting the JSON stored in the database
  to be deserialized into arbitrary ruby objects.

  See the json_serializer/xml_serializer changes mentioned in
  the Other Improvements section.

* The reimplemented query extension is not completely backwards
  compatible.  For example, inside a query block, self refers to the
  proxy object instead of a dataset, and calling methods that return
  rows no longer raises an exception.

* The metadata parsing methods on PostgreSQL no longer work with
  unqualified tables where the table is not in the schema search
  path.  This makes metadata parsing consistent with how datasets
  operate.  For tables outside the schema search path, you must
  qualify it before use now.

  Additionally, using a nonexistent table name will raise an
  exception instead of returning empty results in some cases.

* The Dataset#def_mutation_method instance method has been removed.
  This method added mutation methods directly on the dataset instance,
  which is generally not desired.  Using the def_mutation_method class
  method with the :module option is now the recommended approach.

* The switch to using ESCAPE for LIKE characters is backwards
  incompatible on databases that don't use escaping by default, 
  when backslash is used in a LIKE pattern as a regular character.
  Now you have to double the backslash in the pattern.

* Database#database_error_regexps private method now can return any
  enumerable yielding regexp/exception class pairs, it is no longer
  specified to return a hash.

---

### Doc Release Notes 3.46.0 (`doc/release_notes/3.46.0.txt`)

= New Features
 
* Dataset#first! has been added.  This is identical to #first,
  except where #first would return nil due to no row matching,
  #first! raises a Sequel::NoMatchingRow exception.  The main
  benefit here is that a standard exception class is now used,
  so external libraries can deal with these exceptions appropriately
  (such as web applications returning a 404 error).

* Dataset#with_pk! has been added to model datasets.  Similar to
  #first!, this raises a Sequel::NoMatchingRow exception instead of
  returning nil if there is no matching row.

* A drop_foreign_key method has been added to the alter_table
  generator:

    alter_table(:tab){drop_foreign_key :col}

  This relies on foreign_key_list working and including the name
  of the foreign key.  Previously, you'd have to drop the foreign key
  constraint before dropping the column in some cases.

* Column constraints can now be named using :*_constraint_name
  options:

    create_table(:tab) do
      primary_key :id, :primary_key_constraint_name=>:pk_name
      foreign_key :t_id, :t, :foreign_key_constraint_name=>:fk_name,
        :unique=>true, :unique_constraint_name=>:uk_name
    end

  This makes it easier to name constraints, which has always been
  recommended as it makes it easier to drop such constraints in the
  future.

* On Microsoft SQL Server, Dataset#cross_apply and #outer_apply have
  been added to use CROSS/OUTER APPLY.  These are useful if you
  want to join a table to the output of a function that takes the
  table as an argument.

= Other Improvements

* The connection pools are now faster when using the
  :connection_handling=>:queue option.

* External connection pool classes can now be loaded automatically by
  the :pool_class option.

* Database#each_server now raises if not given a block.  Previously,
  it just leaked Database references.

* On Microsoft SQL Server, ] characters are now escaped correctly in
  identifiers.

* On PostgreSQL, infinite dates are also handled when using
  Database#convert_infinite_timestamps.  Previously, infinite dates
  were incorrectly converted to 0000-01-01.

* The associations, composition, serialization, and dirty plugins
  now clear caches stored in the instance in some additional cases,
  such as when saving model instances when the dataset supports
  insert_select.

* Model#validates_type in the validation_helpers plugin now handles
  false values correctly.

* The string_stripper plugin has been fixed to not change the result
  of Model.set_dataset.

* You can now drop primary key constraints on H2, using:

    alter_table(:tab){drop_constraint :foo, :type=>:primary_key}

* The jdbc/as400 adapter has been fixed, it was broken starting in
  Sequel 3.44.0.

* A Security guide has been added explaining various security issues
  to think about when using Sequel.

= Backwards Compatibility

* The change to make associations, composition, serialization, and
  dirty now clear caches after saving when the dataset supports
  insert_select can break code that expected the previous behavior.
  For example:

    artist = Artist[1]
    artist.has_albums # => false

    album = Album.new(:artist=>artist)
    def album.after_create
      super
      artist.update(:has_albums=>true)
    end
    album.save

    artist.has_albums # => false

  Such code should either refresh the artist after saving the album,
  or use album.artist.has_albums.  You already had to do that if
  the dataset did not support insert_select; the impetus for this
  change was to make the behavior consistent.

* Decimal/numeric columns are now strictly typecast by default,
  similar to integer and real/double precision columns.  If you want
  the previous loose typecasting to for decimal/numeric columns,
  use the looser_typecasting extension.

* External adapters that called Database.set_adapter_scheme with a
  string should change to using a symbol.

* Dataset#select_map, #select_order_map, and #get now raise an
  exception if they are passed a plain string inside an array.  
  If you do want to use a plain string, you now need to alias it:
  
    dataset.get([Sequel.as('string', :some_alias)])

= Sequel 4 Implementation Planning

* Sequel 4 implementation planning has begun.  If you want to view
  and/or provide feedback on the implementation plan, see
  https://github.com/jeremyevans/sequel-4-plans

---

### Doc Release Notes 3.47.0 (`doc/release_notes/3.47.0.txt`)

= New Plugins

* An auto_validations plugin has been added, which automatically
  adds not null, type, and unique validations based on information
  obtained from parsing the database schema.  If you don't
  require customization of the validation error message per
  column, this can significantly DRY up validation code.  Currently
  this plugin requires the database support index parsing; that
  restriction will be removed in Sequel 4.

* An input_transformer plugin has been added, for automatically
  running a transformation proc on all model column setter
  input before use.  This is a generalization of the
  string_stripper plugin, allowing arbitrary modifications
  to the input.

* An error_splitter plugin has been added, for splitting validation
  errors applying to multiple columns into a separate validation
  error per column.  This is useful if you want to to include such
  errors when using Errors#on to get all errors on the column. In
  general, only uniqueness errors apply to multiple columns, so
  those are the only errors likely to be affected.

= Other New Features

* Database.extension has been added, allowing you to load an
  extension into all future databases.  This is similar to loading a
  plugin into Sequel::Model itself.  For example, if you want all
  Database instances to use the query_literals extension, run the
  following before creating your Database instances:

    Sequel::Database.extension :query_literals

* Database.after_initialize has been added for running a hook
  on all new databases created.

* Model.default_set_fields_options has been added, allowing you
  to set the default options for the #set_fields and #update_fields
  methods.  This is useful if you want to make :missing=>:raise
  or :missing=>:skip the default behavior.

* The :setter, :adder, :remover, and :clearer association options
  have been added.  These allow you to override the default
  implementation used to modify the association.  :setter affects
  the *_to_one setter method, :adder the *_to_many add_* method,
  :remover the *_to_many remove_* method, and :clearer the
  *_to_many remove_all_* method.

  Previously, you had to override a private method to get the same
  behavior, this just offers a nicer API for that.

* A :keep_reference Database option has been added.  When set to
  false, a reference to the Database instance is not kept in
  Sequel::DATABASES.  This is designed for Database instances
  created by libraries, so they don't accidentally get chosen as
  the default Sequel::Model database.

* Model#modified! now accepts a column and marks that column
  as changed.  This is useful if you plan on mutating the column
  value as opposed to reassigning it.

* Model#modified? now accepts a column and returns whether the
  column has been changed.

* The migrators now support an :allow_missing_migration_files
  option, which makes them silently ignore errors related to
  missing migration files.

* validates_schema_types has been added to validation_helpers,
  which validates that the column values are instances of the
  expected ruby type for the given database schema type.  This
  is a more robust version of the validates_not_string
  extension, and users of validates_not_string are encouraged
  to switch soon, as validates_not_string is going away in
  Sequel 4.

  validates_schema_type has been added to validation_class_methods,
  which performs the same validation, but it requires the columns
  be listed explicitly.

  validates_type in validation_helpers has been expanded to
  accept an array of allowable classes.

  Related to this is the addition of Database#schema_type_class for
  returning the type class(es) for the given schema type symbol.

* validates_not_null has been added to the validation_helpers
  plugin.  This is similar to the validates_presence validation,
  but only checks for nil values, allowing empty/blank strings.

* In the caching plugin, when the :ignore_exceptions option is true,
  exceptions raised when deleting an object from the cache are now
  ignored correctly.

* On PostgreSQL, Sequel now supports a :search_path Database
  option to automatically set the client connection search_path.
  This allows you to control which schemas do no require
  qualification, and in which order to check schemas when
  referencing unqualified objects.  If you were using the
  default_schema setting, it is recommended that you switch
  to using :search_path instead.

* The pg_array extension can now register array types on a
  per-Database basis via Database#register_array_type. Previously,
  only global registration of array types was allowed.  Additionally,
  when registering array types on a per-Database basis, the oids can
  be looked up automatically, making it possible to register array
  types with just a type name:

    DB.register_array_type(:interval)

* The pg_array extension now automatically creates conversion
  procs for array types of all named types used by the
  database.  This means that if you use the pg_array and
  pg_hstore extensions, the hstore[] type is now handled
  correctly.

* The postgres adapter now supports :use_iso_date_format and
  :convert_infinite_timestamps Database options.  Previously,
  use_iso_date_format was only a global setting, and
  convert_infinite_timestamps could only be set after
  initialization.

* Database#supports_schema_parsing? has been added to check
  if schema parsing via the Database#schema method is
  supported.

= Other Improvements

* A race condition related to prepared_sql for newly prepared
  statements has been fixed.

* Dataset#get now works correctly if given an array with multiple
  columns if there were no returned rows.

* The plugins that ship with Sequel now handle frozen model instances
  correctly.

* Freezing of model instances now works correctly for models without
  primary keys.

* Database constraints added with the constraint_validations
  plugin now handle NULL values correctly if the :allow_nil=>true
  setting is used.

* The  pagination, pretty_table, query, schema_caching,
  schema_dumper, and select_remove extensions can now be
  loaded by Database#extension.  If you are loading them
  globally via Sequel.extension, switch to using
  Database#extension, since that will be required starting
  in Sequel 4.

* The lazy_attributes plugin no longer uses the identity_map plugin
  internally, and eager loading lazy attributes now works correctly
  without an active identity map.

* The many_to_one_pk_lookup plugin now handles many more corner
  cases, and should be safe to enable by default.

* The static_cache plugin now has optimized implementations of
  Model.map, .to_hash, and .to_hash_groups which work without a
  database query.  Model.count without arguments has also been
  optimized to not require a database query.

* Fetching new records has been made faster when using the
  update_primary_key plugin, since it was changed to cache the primary
  key values lazily.

* When using the update_primary_key plugin, if the primary key
  changes, clear the associations cache of all non-many_to_one
  associations (since those will likely be based on the primary
  key).

* The pg_typecast_on_load plugin no longer errors if given a
  column that doesn't have a matching oid conversion proc.

* Handling of domain types on PostgreSQL has been significantly
  improved.  Domain type columns now have correct model
  typecasting, and the pg_row extension correctly sets up
  conversion procs for domain types inside composite types.

* Postgres::HStoreOp#- now automatically casts string input to
  text, so that PostgreSQL doesn't assume the string is an
  hstore.

* Postgres::PGRangeOp#starts_before and #ends_after have been
  renamed to #ends_before and #starts_after.  The previous
  names were misleading.  The old names are still available
  for backwards compatibility, but they will be removed in the
  Sequel 4.

* The pg_row plugin now handles aliased tables correctly.

* Model#validate in the validation_class_methods plugin no
  longer skips validate methods in superclasses or previously
  loaded plugins.

* Loading the touch plugin into a model subclass after it has
  been loaded into a model superclass no longer ignores
  inherited touched associations.

* Sequel no longer resets the conversion procs for the
  Database instance when using Database#extension to load a
  pg_* extension that adds global conversion procs.  Instead,
  the global conversion procs are added to the instance-specific
  conversion procs.  The result of this is that manually added
  conversion procs will not be lost if an extension is loaded
  afterward.

* The jdbc adapter now references the driver class before loading
  subadapter specific code, which can fix issues if the database
  tries to connect on initialization (such as the jdbc/postgres
  adapter if the pg_hstore extension is loaded previously).

* A guide describing Sequel's support for advanced PostgreSQL
  features has been added.

= Backwards Compatibility

* If you have already used the constraint_validations plugin to
  create validations with the :allow_nil=>true option, you should
  drop and regenerate those constraints to ensure they handle NULL
  values correctly.

* The change to make PostgreSQL automatically handle domain
  types can break previous code that set up special conversions
  and typecasts per domain type.  In the schema parsing, if you
  want to get the domain type information, it will be contained
  in the :db_domain_type and :domain_oid schema entries.

* Sequel::Postgres.use_iso_date_format is now only defined if
  you are using the postgres adapter.  Previously, it could
  be defined when using other adapters with a pg_* extension,
  even though the setting had no effect in that case.

* The validation_class_methods plugin now copies validations into
  the subclass upon inheritance, instead of recursing into the
  superclass on validation.  This makes it more similar to how
  all the other Sequel plugins work.  However, it also means that
  if you add validations to a superclass after creating a
  subclass, the subclass won't have those validations.  Additionally
  if you skip superclass validations in a child class after creating
  a grandchild class, the grandchild class could still have the
  parent class's validations.

* The validates_unique validation in validation_helpers no longer
  attempts to do the uniqueness query if the underlying columns
  have validation errors.  The reasoning behind this is that if the
  underlying columns are not valid, the uniqueness query can cause
  a DatabaseError.

* If you were passing strings in hstore format to
  Postgres::HStoreOp#-, you should manually cast them to hstore:

    hstore_op - Sequel.cast('a=>b', :hstore)

* The default validation error message for validates_type has been
  modified.

* Database#schema_column_type was made public accidentally by an
  adapter and a few extensions.  That has been fixed, but if you
  were calling it with an explicit receiver and it happened to
  work by accident before, you'll need to update your code.

= Sequel 4 Implementation Planning

* Sequel 4 implementation work will begin shortly.  All Sequel users
  are encouraged to read about the proposed changes and provide
  feedback on the implementation plan. For details, see
  https://github.com/jeremyevans/sequel-4-plans.

---

### Doc Release Notes 3.48.0 (`doc/release_notes/3.48.0.txt`)

= Deprecation Warnings

The main change in Sequel 3.48.0 is the deprecation of Sequel
features that will be modified, moved, or removed in Sequel 4.
For the reasoning behind these changes, please review the
commits logs at
https://github.com/jeremyevans/sequel-4-plans/commits/master

== Deprecation Logging

If you use a deprecated method or feature, Sequel will by default
print a deprecation message and 10 lines of backtrace to stderr
to easily allow you to figure out which code needs to be
updated.  You can change where the deprecation messages go and how
many lines of backtrace are given using the following:

  # Log deprecation information to a file
  Sequel::Deprecation.output = File.open('deprecated.txt', 'wb')
  
  # Turn off all deprecation logging
  Sequel::Deprecation.output = nil

  # Use 5 lines of backtrace when logging deprecation messages
  Sequel::Deprecation.backtrace_filter = 5
  
  # Use all backtrace lines when logging deprecation messages
  Sequel::Deprecation.backtrace_filter = true
  
  # Don't include backtraces in the deprecation logging
  Sequel::Deprecation.backtrace_filter = false

  # Select which backtrace lines to output
  Sequel::Deprecation.backtrace_filter = \
    lambda{|line, line_no| line_no < 3 || line =~ /my_app/}

== Major Change

* The core extensions will no longer be loaded by default. You will
  have to use `Sequel.extension :core_extensions` to load the core
  extensions.

* The Symbol#[] and Symbol#{<,>,<=,>=} methods will no longer be
  provided by the core extensions on ruby 1.8. You will have to
  use `Sequel.extension :ruby18_symbol_extensions` to use them.

== Core Behavior Changes

* Dataset#filter becomes an alias for #where, and #exclude
  becomes an alias for #exclude_where. You will have to
  use `DB.extension :filter_having` to get the previous behavior.
  Dataset#and and #or will also only affect the WHERE clause.

* Dataset#and, #or, and #invert will not raise errors for no existing
  filter.

* Dataset#select_more becomes an alias for #select_append.

* Dataset#select and #from will not longer consider a hash argument as
  an alias specification. You will have to use
  `DB.extension :hash_aliases` to get the previous behavior.

* Database#dataset and Dataset.new will not take an options hash.

* Database#transaction :disconnect=>:retry option will be removed.

* Calling Dataset#add_graph_aliases before #graph or #set_graph_aliases
  will raise an Error.

* Datasets will have a frozen options hash by default.

* Dataset#set_overrides and #set_defaults will move to the
  set_overrides extension.

* Sequel.empty_array_handle_nulls will be removed.  To get the
  empty_array_handle_nulls = false behavior, you will have to
  use `DB.extension :empty_array_ignore_nulls`.

* The second argument to Dataset #union, #intersect, and #except must
  be an options hash if it is given.

* The fourth argument to Dataset #join_table must be an options
  hash if it is given.

* Using a mismatched number of placeholders and arguments in a
  placeholder literal string will raise an error.

* Dataset#graph_each will move to the graph_each extension.

* Database#default_schema will be removed.

* Dataset#[]= will be moved to the sequel_3_dataset_methods
  extension.

* Dataset#insert_multiple will be moved to the
  sequel_3_dataset_methods extension.

* Dataset#set will be moved to the sequel_3_dataset_methods
  extension.

* Dataset#to_csv will be moved to the sequel_3_dataset_methods
  extension.

* Dataset#db= and #opts= setters will be moved to the
  sequel_3_dataset_methods extension.

* Dataset#qualify_to and #qualify_to_first_source will be moved to
  the sequel_3_dataset_methods extension.

* Remove default methods that raise Sequel::NotImplemented: 
  Database#connect, #execute, #foreign_key_list, #indexes, #tables,
  and #views, and Dataset#fetch_rows.

* Sequel::SQL::Expression#to_s will be removed.

* All Dataset methods in Dataset::PUBLIC_APPEND_METHODS except for
  #literal, #quote_identifier, and #quote_schema_table will be
  removed.

* All Dataset methods in Dataset::PRIVATE_APPEND_METHODS will
  be removed.

* Sequel k_require, ts_require, tsk_require, and
  check_requiring_thread will be removed.

* Dataset.def_append_methods will be removed.

* Dataset#table_ref_append will be removed.

* Sequel.virtual_row_instance_eval accessor will be removed.

* Database#reset_schema_utility_dataset will be removed.

== Adapter Behavior Changes

* The Database#do method will be removed from the ado, db2, dbi,
  informix, odbc, openbase, and oracle adapters.

* The jdbc adapter will raise an error when parsing the schema
  for a table if it detects results for the same table name in
  multiple schemas.

* The Database#query method will be removed from the informix
  adapter.

* Dataset#lock on PostgreSQL will check the given lock mode.

* Sequel will check the client_min_messages setting before
  use on PostgreSQL.

* Prepared statement placeholders on PostgreSQL will no longer
  support implicit casting via :$x__type.

== Extension Behavior Changes

* The following extensions will no longer make global changes to
  the Database and Dataset classes: null_dataset, pagination,
  pretty_table, query, schema_caching, schema_dumper,
  select_remove, and to_dot.  These will be changed to
  Database/Dataset specific extensions.
  
* The pg_auto_parameterize and pg_statement_cache extensions will
  be removed.

* Sequel::Dataset.introspect_all_columns will be removed from the
  columns_introspection extension.

* PGRangeOp#starts_before and #ends_after will be removed from the
  pg_range_ops extension.

== Model Behavior Changes

* Model#initialize will accept only one argument.

* The after_initialize hook will be moved to a plugin.

* Move blacklist-based security methods (#set_except, #update_except,
  .set_restricted_columns) to a plugin.

* The :eager_loader and :eager_grapher association option procs will
  always be passed a hash.

* Model string column setters will consider array and hash input to
  be invalid.

* Remove save taking multiple arguments for the columns to save.
  Add Model#save :columns option for saving specific columns. 

* Don't automatically choose a reciprocal association with a condition
  or block.

* Don't automatically set up reciprocal associations if multiple ones
  match.

* Model::Errors#[] will no longer modify the receiver.  If you want
  autovivification, use the active_model plugin. 

* Model.set_primary_key will not longer accept composite keys as
  multiple arguments.

* The correlated_subquery eager limit strategy will be removed.

* The following Model class dataset methods will be removed: print,
  each_page, paginate, set, add_graph_aliases, insert_multiple, query,
  set_overrides, set_defaults, to_csv.

* The Model.{destroy,delete,update} class dataset methods will be
  moved to the scissors plugin.

* Model#pk_or_nil will be removed.

* Model#set_values will no longer be called directly by any Sequel
  code, and overriding it is deprecated. It will be removed in Sequel
  4.1.

* Model.cache_anonymous_models accessor will move to Sequel module.

* Model::InstanceMethods.class_attr_overridable and
  .class_attr_reader will be removed.

* The :one_to_one option check for one_to_many associations will
  be removed.

== Plugin Behavior Changes

* Public dataset methods will no longer have class methods
  automatically added.

* The validates_not_string validation will be removed from the
  validation_class_methods and validation_helpers plugin.

* In the json_serializer plugin, the to_json :root=>true option
  means :root=>:collection instead of :root=>:both.

* In the json_serializer plugin, the to_json :naked option will
  default to true, and there will not be way to add the JSON.create_id
  automatically.

* In the json_serializer plugin, from_json will no longer automatically
  delete the JSON.create_id key from the input hash.

* The #to_json and #to_xml :all_columns and :all_associations options
  in the json_serializer and xml_serializer plugins will be removed.

* The Model.json_create method will be removed from the
  json_serializer plugin.

* The validates_type validation will raise validation errors for nil
  if :allow_nil=>true is not used.

* auto_validate_presence_columns will be removed from the
  auto_validations plugin 

* The identity_map plugin will be removed.

== Internal Changes

* The sequel_core.rb and sequel_model.rb files will be removed.

* Dataset#{quote_identifiers,identifier_output_method,
  identifier_input_method} will assume Database implements the
  methods.

= Forwards Compatibility

Not all changes planned in Sequel 4 have deprecation warnings.
The following changes will be made in Sequel 4 but do not have
deprecation warnings in 3.48.0:

* The threaded connection pools will default to
  :connection_handling=>:queue.  You can manually set
  :connection_handling=>:stack to get the current behavior.

* Dataset#join_table will default to :qualify=>:deep.  You can
  manually set :qualify=>:symbol to get the current behavior.  This
  can be set at a global level by overriding
  Dataset#default_join_table_qualification.

* Model.raise_on_typecast_failure will default to false.  Set this to
  true to get the current behavior of raising typecast errors in the
  setter methods.

* Model#save will no longer call Model#_refresh or Model#set_values
  internally after an insert.  Manually refreshes will be treated
  differently than after creation refreshes in Sequel 4.

* On SQLite, integer_booleans will be true by default.  Set this to
  false to get the current behavior of 't' for true and 'f' for false.

* On SQLite, use_timestamp_timezones will be false by default.  Set
  this to true to get the current behavior with timezone information
  in timestamps.

* The default value for most option hash arguments will be an empty
  frozen hash.  If you are overriding methods and modifying option
  hashes, fix your code.

* The defaults_setter plugin will work in a lazy manner instead of
  an eager manner.  If you must have the values hash contain defaults
  for new objects (instead of just getting defaults from getter
  methods), you'll need to fork the current plugin.

* Model#set_all will allow setting the primary key columns.

* The many_to_one_pk_lookup plugin will be integrated into the
  default associations support.

* The association_autoreloading plugin will be integrated into the
  default associations support.

* Plugins will extend the class with ClassMethods before including
  InstanceMethods in the class.

* Dataset#get, #select_map, and #select_order_map will automatically
  add aliases for unaliased expressions if given a single expression.

* Database#tables and #views on PostgreSQL will check against
  the current schemas in the search path.

* Sequel::SQL::SQLArray alias for ValueList will be removed.

* Sequel::SQL::NoBooleanInputMethods will be removed.

* Sequel::NotImplemented will be removed.

* Sequel::Model::EMPTY_INSTANCE_VARIABLES will be removed.

* Sequel will no longer provide a default database for the adapter or
  integration specs.

= New Features

* You can now choose which Errors class to use on a per model basis
  by overriding Model#errors_class.

* The following Database methods have been added to check for support:
  supports_index_parsing?, supports_foreign_key_parsing?,
  support_table_listing?, supports_view_listing?.

* The pg_hstore_ops extension now integrates with the pg_array,
  pg_hstore, and pg_array_ops extensions, allowing you to pass in
  arrays and hashes to be treated as PGArrays and HStores, and
  returning ArrayOps for PostgreSQL functions/operators that
  return arrays.

* Sequel.object_to_json and Sequel.json_parser_error_class
  have been added and all internal json usage uses them, so you
  can now override these methods if you want to use an alternative
  json library with Sequel.

* The association_proxies plugin now accepts a block allowing the
  user control over which methods are proxied to the dataset or
  the cached array of instances.  You can base the decision on
  where to send the method using a variety of factors including
  the method name, the method arguments, the state of the current
  instance, or the related association.  Here's an example of a
  simple case just depending on the name of the method; 

    Model.plugin :association_proxies do |opts|
     [:find, :where, :create].include?(opts[:method])
    end

  If the block returns true, the method is sent to the dataset,
  otherwise it is sent to the array of associated objects.

* The auto_validations plugin now accepts a :not_null=>:presence
  option, for doing a presence validation instead of a not_null
  validation.  This is useful for databases with NOT NULL
  constraints where you also want to disallow empty strings.

* The auto_validations plugin now validates against explicit nil
  values in NOT NULL columns that have defaults.

* The constraint_validations plugin now reflects validations, using
  Model.constraint_validation_reflections.

    Model.constraint_validation_reflections[:column]
    # => [[:presence, {}],
    #     [:max_length, {:argument=>255, :message=>'just too long'}]]

* The constraint_validations plugin can now be set to pass specific
  validations options to the validation_helpers plugin.  This can be
  useful if using the auto_validations plugin with this plugin to
  avoid duplicate error messages for nil values:

    Model.plugin :constraint_validations,
      :validates_options=>{:presence=>{:allow_nil=>true}}

* The named_timezones extension can now be loaded as a database
  extension, which allows for automatic conversions of string
  timezones:

    DB.extension :named_timezones
    DB.timezone = 'America/Los_Angeles'

* Offsets are now emulated by Microsoft Access using a combination
  of reverse orders and total counts.  This is slow, especially on
  large datasets, but probably better than having no support at all.
  It is also possible to use the same code to support Microsoft
  SQL Server 2000, but as Sequel does not support that (minimum
  supported version is 2005), you have to do it manually:

    Sequel.require 'adapters/utils/emulate_offset_with_reverse_and_count'
    DB.extend_datasets Sequel::EmulateOffsetWithReverseAndCount

= Other Improvements

* Dataset#clone is now faster.

* Database methods that create datasets (fetch, from, select, get)
  are now faster.

* Model.with_pk and .with_pk! are now faster.

* Dataset#or now just clones if given an empty argument, similar
  to Dataset#where.

* Sequel now correctly frees statements after using them in the
  ibmdb adapter.  Previously, they weren't freed until GC, which
  could result in errors if all available handles are in use.

* Dataset creation is now faster on Microsoft SQL Server.

* The mediumint and mediumtext types are now recognized on MySQL.

* The ado adapter now handles disconnecting an already disconnected
  connection.

* The auto_validations plugin now works on databases that don't
  support index parsing.  However, it will not set up automatic
  uniqueness validations on such databases.

* The validation_helpers is more strict in some cases when checking
  for nil values, using a specific nil check instead of general
  falsely check.

* The table inheritance plugins now correctly handle usage of
  set_dataset in a subclass.

* The bin/sequel command line tool now has specs.

= Backwards Compatibility

* Sequel now uses aliases for many internal Dataset#get calls, such
  as those used by table_exists? and max. 

* Sequel now no longer uses class variables internally.  Instead,
  instance variables of the Sequel::Database class are used.

* Sequel now sets up the identifier mangling methods on Database
  initialization instead of on first use.

* The private Database#adapter_initialize method has been added for
  per adapter configuration.  All internal adapters have been switched
  to use this method instead of overriding initialize, and all
  external adapters should as well.  This makes sure that Database
  instances are not added to Sequel::DATABASES until they have been
  completely initialized.

* Virtual row blocks no longer convert their return values to an array.
  Among other things, this means that having a virtual row block return
  a hash works as expected.

* The private Dataset#hash_key_symbol method now only takes a single
  argument.

* Database#constraint_validations in the constraint_validations plugin
  now returns raw hash rows, instead of arrays of validation method
  call arguments.

* Dataset#count now uses a lowercase count function in the SQL.

* Passing a non-String or Hash as the first argument to an adapter
  method (e.g. Sequel.postgres(1)) now raises an error.  Before, this used
  to work on some adapters that implicitly converted the database
  name to a string.

* The stats and dcov rake tasks were removed.

---

### Doc Release Notes 3.5.0 (`doc/release_notes/3.5.0.txt`)

New Plugins
-----------

* A class_table_inheritance plugin has been added, supporting model
  inheritance in the database using a table-per-model-class approach.
  Each table stores only attributes unique to that model or subclass
  hierarchy.
  
  For example, with this hierarchy:

                Employee
               /        \
            Staff     Manager
                         |
                      Executive

  the following database schema may be used (table - columns):

  * employees - id, name, kind
  * staff - id, manager_id
  * managers - id, num_staff
  * executives - id, num_managers

  The class_table_inheritance plugin assumes that the main table
  (e.g. employees) has a primary key field (usually
  autoincrementing), and all other tables have a foreign key of the
  same name that points to the same key in their superclass's table.
  For example:

  * employees.id  - primary key, autoincrementing
  * staff.id - foreign key referencing employees(id)
  * managers.id - foreign key referencing employees(id)
  * executives.id - foreign key referencing managers(id)

  When using the class_table_inheritance plugin, subclasses use joined
  datasets:

    Employee.dataset.sql  # SELECT * FROM employees
    Manager.dataset.sql   # SELECT * FROM employees
                          # INNER JOIN managers USING (id)
    Executive.dataset.sql # SELECT * FROM employees
                          # INNER JOIN managers USING (id)
                          # INNER JOIN executives USING (id)

  This allows Executive.all to return instances with all attributes
  loaded.  The plugin overrides deleting, inserting, and updating
  in the model to work with multiple tables, by handling each table
  individually.

  This plugin allows and encourages the use of a :key option to mark
  a column holding the class name.  This allows methods on the
  superclass to return instances of specific subclasses.

    a = Employee.all # [<#Staff>, <#Manager>, <#Executive>]
    
  This plugin requires the lazy_attributes plugin and uses it to
  handle subclass specific attributes that would not be loaded
  when calling superclass methods (since those wouldn't join
  to the subclass tables).  For example:
    
    a.first.values # {:id=>1, name=>'S', :kind=>'Staff'}
    a.first.manager_id # Loads the manager_id attribute from the
                       # database
                       
  The class_table_inheritance plugin requires JOIN USING and
  therefore is not supported on H2 or Microsoft SQL Server, which do
  not support that SQL-92 feature.
  
* An associations_dependencies plugin was added for deleting,
  destroying, or nullifying associated objects when destroying a
  model object.  This just gives an easy way to add the necessary
  before and after destroy hooks.  The following association types
  support the following dependency actions:

  * :many_to_many - :nullify (removes all related entries in join
    table)
  * :many_to_one - :delete, :destroy
  * :one_to_many - :delete, :destroy, :nullify (sets foreign key to
    NULL for all associated objects)
    
  This plugin works directly with the association datasets and does
  not use any cached association values.  The :delete action will
  delete all associated objects from the database in a single SQL
  call. The :destroy action will load each associated object from the
  database and call the destroy method on it.
  
  The plugin call takes a hash of association symbol keys and 
  dependency action symbol values.  Alternatively, you can specify
  additional dependencies later using add_association_dependencies:
  
    Business.plugin :association_dependencies, :address=>:delete
    # or:
    Artist.plugin :association_dependencies
    Artist.add_association_dependencies :albums=>:destroy,
      :reviews=>:delete, :tags=>:nullify

* A force_encoding plugin was added that forces the encoding of
  strings used in model instances.  When model instances are loaded
  from the database, all values in the hash that are strings are
  forced to the given encoding.  Whenever you update a model column
  attribute, the resulting value is forced to a given encoding if the
  value is a string.  There are two ways to specify the encoding.
  You can either do so in the plugin call itself, or via the
  forced_encoding class accessor:
  
    class Album < Sequel::Model
      plugin :force_encoding, 'UTF-8'
      # or
      plugin :force_encoding
      self.forced_encoding = 'UTF-8'
    end
    
  This plugin only works on ruby 1.9, since strings don't have
  encodings in 1.8.
  
* A typecast_on_load plugin was added, for fixing bad database
  typecasting when loading model objects. Most of Sequel's database
  adapters don't have complete control over typecasting, and may
  return columns that aren't typecast correctly (with correct being
  defined as how the model object would typecast the same column
  values).

  This plugin modifies Model.load to call the setter methods (which
  typecast by default) for all columns given.  You can either specify
  the columns to typecast on load in the plugin call itself, or
  afterwards using add_typecast_on_load_columns:

    Album.plugin :typecast_on_load, :release_date, :record_date
    # or:
    Album.plugin :typecast_on_load
    Album.add_typecast_on_load_columns :release_date, :record_date

  If the database returns release_date and record_date columns as
  strings instead of dates, this will ensure that if you access those
  columns through the model object, you'll get Date objects instead of
  strings.

* A touch plugin was added, which adds Model#touch for updating an
  instance's timestamp, as well as touching associations when an
  instance is updated or destroyed.
  
  The Model#touch instance method saves the object with a modified
  timestamp.  By default, it uses the :updated_at column, but you can
  set which column to use. It also supports touching of associations,
  so that when the current model object is updated or destroyed, the
  associated rows in the database can have their modified timestamp
  updated to the current timestamp.  Example:
  
    class Album < Sequel::Model
      plugin :touch, :column=>:modified_on, :associations=>:artist
    end

* A subclasses plugin was added, for recording all of a models
  subclasses and descendent classes.  Direct subclasses are available
  via the subclasses method, and all descendent classes are available
  via the descendents method:

    c = Class.new(Sequel::Model)
    c.plugin :subclasses
    sc1 = Class.new(c)
    sc2 = Class.new(c)
    ssc1 = Class.new(sc1)
    c.subclasses    # [sc1, sc2]
    sc1.subclasses  # [ssc1]
    sc2.subclasses  # []
    ssc1.subclasses # []
    c.descendents   # [sc1, ssc1, sc2]

  The main use case for this is if you want to modify all models
  after the model subclasses have been created.  Since mutable
  options are copied when subclassing, modifying parent classes
  does not affect current subclasses, only future ones.  The
  subclasses plugin allows you get all subclasses so that you can
  easily modify them.  The plugin only records subclasses
  created after the plugin call, though.

* An active_model plugin was added, giving Sequel::Model an
  ActiveModel complaint API, in so much as it passes the
  ActiveModel::Lint tests.

New Extensions
--------------

* A named_timezones extension was added, allowing you to use named
  timezones such as "America/Los_Angeles" (the default Sequel
  timezone support only supports UTC or local time). This extension
  requires TZInfo.  It also sets the Sequel.datetime_class to 
  DateTime, so database timestamps will be returned as DateTime
  instances instead of Time instances.  This is because ruby's
  Time class doesn't support timezones other than UTC and local time.
  
  This plugin allows you to pass either strings or TZInfo::Timezone
  instance to Sequel.database_timezone=, application_timezone=, and
  typecast_timezone=.  If a string is passed, it is converted to a
  TZInfo::Timezone using TZInfo::Timezone.get.

  Let's say you have the database server in New York and the
  application server in Los Angeles.  For historical reasons, data
  is stored in local New York time, but the application server only
  services clients in Los Angeles, so you want to use New York
  time in the database and Los Angeles time in the application.  This
  is easily done via:

    Sequel.database_timezone = 'America/New_York'
    Sequel.application_timezone = 'America/Los_Angeles'

  Then, before timestamps are stored in the database, they are
  converted to New York time.  When timestamps are retrieved from the
  database, they are converted to Los Angeles time.

* A thread_local_timezones extension was added.  This allows you to
  set a per-thread timezone that will override the default global
  timezone while the thread is executing.  The main use case is for
  web applications that execute each request in its own thread, and
  want to set the timezones based on the request.  The most common
  example is having the database always store time in UTC, but have
  the application deal with the timezone of the current user.  That
  can be done with:
  
    Sequel.database_timezone = :utc
    # In each thread:
    Sequel.thread_application_timezone = current_user.timezone

  This extension is designed to work with the named_timezones
  extension.
  
* An sql_expr extension was added that adds .sql_expr methods to
  all objects, giving them easy access to Sequel's DSL:
  
    1.sql_expr < :a     # 1 < a
    false.sql_expr & :a # FALSE AND a
    true.sql_expr | :a  # TRUE OR a
    ~nil.sql_expr       # NOT NULL
    "a".sql_expr + "b"  # 'a' || 'b'

  Proc#sql_expr uses a virtual row:

    proc{[[a, b], [a, c]]}.sql_expr | :x
    # (((a = b) AND (a = c)) OR x)

* A looser_typecasting extension was added, for using to_f and to_i
  instead of the more strict Kernel.Float and Kernel.Integer when
  typecasting floats and integers. To use it, you should extend the
  database with the Sequel::LooserTypecasting module after loading
  the extension:

    Sequel.extension :looser_typecasting
    DB.extend(Sequel::LooserTypecasting)

  This makes the behavior more like ActiveRecord:
  
    a = Artist.new(:num_albums=>'a')
    a.num_albums # => 0

Other New Features
------------------

* Associations now support composite keys.  All of the :*key options
  options now accept arrays of symbols instead of plain symbols.
  Example:
  
    Artist.primary_key # [:name, :city]
    Album.many_to_one :artist, :key=>[:artist_name, :artist_city]
    Artist.one_to_many :albums, :key=>[:artist_name, :artist_city]
    
  All association types are supported, including the built-in
  many_to_many association and the many_through_many plugin.  Both
  methods of eager loading work with composite keys for all
  association types. Setter and add/remove/remove_all methods
  also now work with composite keys.
  
* Associations now respect a :validate option, which can be set to
  false to not validate when implicitly saving associated objects.
  
  There isn't a lot of implicit saving in Sequel's association
  methods, but this gives the user the control over validation when
  the association methods implicitly save an object.

* In addition to the regular association methods, the
  nested_attributes plugin was also updated to respect the
  :validate_association option. It was also modified to not validate
  associated objects twice, once when the parent object was validated
  and again when the associated object was saved.  Additionally, if
  you pass :validate=>false to the save method when saving the parent
  object, it will not longer attempt to validate associated objects
  when saving them.

* Dataset#insert and #insert_sql were refactored and now support the
  following API:
  
  * No arguments - Treat as a single empty hash argument
  * Single argument:
    * Hash - Use keys as columns and values as values
    * Array - Use as values, without specifying columns
    * Dataset - Use a subselect, without specifying columns
    * LiteralString - Use as the values
  * 2 arguments:
    * Array, Array - Use first array as keys, second as values
    * Array, Dataset - Use a subselect, with the array as columns
    * Array, LiteralString - Use LiteralString as the values, with
      the array as the columns
  * Anything else: Treat all given values an an array of values

* Graphing now works with previously joined datasets.  The main use
  case of this is when eagerly loading (via eager_graph) model
  associations for models backed by joined datasets, such as those
  created by the class_table_inheritance plugin.
  
* Sequel.virtual_row was added allowing you to easily use the
  VirtualRow support outside of select, order, and filter calls:
  
    net_benefit = Sequel.virtual_row{revenue > cost}
    good_employee = Sequel.virtual_row{num_commendations > 0}
    fire = ~net_benefit & ~good_employee
    demote = ~net_benefit & good_employee
    promote = net_benefit & good_employee
    DB[:employees].filter(fire).update(:employed=>false)
    DB[:employees].filter(demote).update(:rank=>:rank-1)
    DB[:employees].filter(promote).update(:rank=>:rank+1)

* When Sequel wraps exception in its own classes (to provide database
  independence), it now keeps the wrapped exception available in
  a wrapped_exception accessor.  This allows you to more easily
  determine the wrapped exception class, without resorting to parsing
  the exception message.
  
    begin
      DB.run('...')
    rescue Sequel::DatabaseError => e
      case e.wrapped_exception
      when Mysql::Error
        ...
      when PGError
        ...
      end
    end
    
* The MySQL adapter now supports a Dataset#split_multiple_result_sets
  method that yields arrays of rows (one per result set), instead of
  rows.  This allows you to submit multiple statements at the same
  time (or call a stored procedure that returns multiple result
  sets), and know which rows are related to which result sets.
  
  This violates a lot of Sequel's internal assumptions and should be
  used with care.  Existing row_procs are modified to work correctly,
  but graphing will not work on these datasets.

* The ADO adapter now accepts a :conn_string option and uses that
  as the full ADO connection string.  This can be used to connect to
  any datasource ADO supports, such as Microsoft Excel.
  
* The Microsoft SQL Server shared adapter now supports a
  Database#server_version method.
  
* The Microsoft SQL Server shared adapter now supports updating and
  deleting from joined datasets.
  
* The Microsoft SQL Server shared adapter now supports a
  Dataset#output method that uses the OUTPUT clause.

* Model#_save now calls either Model#_insert or Model#_update for
  inserting/updating the row in the database.  This allows for easier
  overriding when you want to allow creating and updating model
  objects backed by a joined dataset.
  
* Dataset#graph now takes a :from_self_alias option specifying the
  alias to use for the subselect created if the receiver is a joined
  but not yet graphed dataset.  It defaults to the first source table
  in the receiver.

Other Improvements
------------------

* Typecasting model attributes is now done before checking existing
  values, instead of after.  Before, the code for the model attribute
  setters would compare the given value to the existing entry.  If it
  didn't match, the value was typecasted and then assigned.  That led
  to the following situation:

    a = Album[1]
    a.num_tracks # => 10
    params # => {'num_tracks'=>'10'}
    a.set(params)
    a.changed_columns # => [:num_tracks]

  The new behavior typecasts the value first, and only sets it and
  records the column as changed if it doesn't match the typecasted
  value.
  
* Model#modified? is now always true if the record is new.  modified?
  indicates the instance's status relative to the database, and since
  a new object is not yet in the database, and saving the object
  would add it, the object is considered modified. A consequence of
  this is that Model#save_changes now always saves if the object is
  new.
  
  If you want to check if there were changes to columns since the
  object was first initialized, you should use
  !changed_columns.empty?, which was the historical way to handle
  the situation.

* The DataObjects (do) adapter now supports DataObjects 0.10.

* Dataset#select_more and Dataset#order_more no longer affect the
  receiver.  They are supposed to just return a modified copy of the
  receiver instead of modifying the receiver itself.  For a few
  versions they have been broken in that they modified the receiver
  in addition to returning a modified copy.
  
* Performance was increased for execution of prepared statements
  with multiple bound variables on MySQL.
  
* On MySQL, database errors raised when preparing statements or
  setting bound variable values are now caught and raised as
  Sequel::DatabaseErrors.
  
* On MySQL, more types of disconnection errors are detected.
  
* When altering columns in MySQL, options such as :unsigned,
  :elements, and :size that are given in the call are now respected.

* MySQL enum defaults are now handled correctly in the schema dumper.

* The schema dumper no longer attempts to use unparseable defaults
  as literals on MySQL, since MySQL does not provide defaults as
  valid literals.

* The emulated offset support in the shared Microsoft SQL Server
  adapter now works better with model classes (or any datasets with
  row_procs).
  
* Microsoft SQL Server now supports using the WITH clause in delete,
  update, and insert calls.
  
* Parsed indexes when connecting to Microsoft SQL Server via JDBC no
  longer include primary key indexes.
  
* Dataset#insert_select now returns nil if disable_insert_returning
  is used in the shared PostgreSQL adapter.  This makes it work as
  expected with model object creation.
  
* Calling Model.set_primary_key with an array of symbols to set
  a composite primary key is now supported.  You can also provide
  multiple symbol arguments to do the same thing.  Before, specifying
  an array of symbols broke the Model.[] optimization.

* Literalization of timezones in timestamps now works correctly on
  Oracle.
  
* __FILE__ and __LINE__ are now used everywhere that eval is called
  with a string, which makes for better backtraces.
  
* The native MySQL adapter now correctly handles returning before
  yielding all result sets.  Previously, this caused a commands out
  of sync error.
  
* Table names in common table expressions are now quoted.

* The Oracle adapter's Dataset#except now accepts a hash, giving it
  the same API as the default Dataset#except.
  
* When connecting to Microsoft SQL Server via ADO, allow
  Dataset#insert to take multiple arguments.
  
* Fractional timestamps are no longer used on ODBC.

* Schema parsing now works on MSSQL when the database is set to not
  quote identifiers.
  
* Timezone offsets are no longer used on Microsoft SQL Server, since
  they only work for the datetimeoffset type.
  
* Only 3 fractional digits in timestamps are u