Commits on Mar 2, 2009
Commits on Feb 26, 2009
  1. Merge branch 'perf'

    committed Feb 26, 2009
  2. Remove SQL::IrregularFunction, no longer used internally

    The only user of this class left was from
    ComplexExpressionMethods#extract, which was changed to use a
    regular Function plus a PlaceholderLiteralString.
    SQL::IrregularFunction was always a bad hack, and the function
    plus placeholder string method is much neater and better all
    This also fixes another String#lit call in the shared SQLite adapter.
    committed Feb 26, 2009
  3. Allow String.lit to take arguments and return a SQL::PlaceholderLiter…

    This useful when you want an SQL fragment to be literalized, but also
    want it to contain other values.  Before, this was hard to do without
    calling Dataset#literal.  Now, it's much easier to deal with:
      column = :user
      pattern = params[:pattern]{|o| o.substring('? from ?'.lit(column, pattern))}
    This commit also changes the internals so that String#lit is never
    called, so Sequel itself won't break if another library defines it.
    committed Feb 26, 2009
Commits on Feb 25, 2009
  1. Make Dataset#order and Dataset#order_more yield a VirtualRow to a block

    This is mostly useful if you want to call an SQL function in an order
    clause on Ruby 1.9.
    committed Feb 25, 2009
  2. Add Model#set_associated_object, used by the many_to_one setter metho…

    …d, for easier overriding
    This is for consistency with the one_to_many and many_to_many
    association methods (e.g. add_associated_object).  It allows you
    to override behavior for all many_to_one setters by overriding a
    single method.
    committed Feb 25, 2009
  3. Remove Database#find_by_table_column_value, add Dataset#with_sql, for…

    … optimization in Model.[]
    I shouldn't have added a database method for this, so back it out.
    The dataset method makes more sense, and I've been wanting to add it
    for a while.  Dataset#static_sql was already taken, so I chose
    Dataset#with_sql.  Add the usual dataset mutation method and model
    dataset methods, and switch Model.[] to use with_sql.
    This new code allows the optimized version to work with models with
    serialized columns, plus models that use datasets with nonstandard
    While here, fix Model.set_dataset so that it removes the simple_table
    if a dataset is given.
    committed Feb 25, 2009
Commits on Feb 24, 2009
  1. Allow use of database independent types when casting

    Previously, types were used as-is when casting.  Now, casting uses
    the same type casting code as the schema methods, so you can specify
    ruby classes and have them changed to database specific types.
    This changes the object used for casts from SQL::IrregularFunction
    SQL::Cast.  SQL::IrregularFunction is now just used for handling
    the SQL EXTRACT function (though it may be used for other similar
    functions in the future).
    This adds an integration test for the feature (in addition to the
    usual specs).  It fails on SQLite because of the way SQLite handles
    casting (returning strings even when you are casting to integer).
    committed Feb 24, 2009
  2. Give association datasets knowledge of the model object that created …

    …them and the related association reflection
    This should make association extensions much more powerful.  Before,
    the :extend association option was near worthless, since association
    datasets were treated just like any other dataset, and didn't have
    the context needed to make decisions based on the values of the
    object that created the association.  Now, you can use association
    extensions such as:
       module FindOrCreate
         def find_or_create(vals)
          first(vals) || association_reflection.associated_class. \
    The above should be a generic find_or_create association dataset
    method that works for any standard one_to_many association:
      Artist.one_to_many :albums, :extend=>FindOrCreate
    You could previously do something similar using an association block
    that added methods to the dataset by using a closure, but that would
    have to be modified per association, doing so generically was not
    committed Feb 24, 2009
Commits on Feb 23, 2009
Commits on Feb 22, 2009
  1. Add an optimization to Model.[] for simple models, with a 30-40% perf…

    …ormance increase
    After some profiling I discovered that Model.[] can spend almost half
    of it's time in producing the SQL to send to the database.  This is
    because it goes through the entire SQL creation process, which is
    very flexible, but not optimized for performance.  If it's possible
    to use static SQL instead of going through the usual SQL generation
    process, there would be a dramatic performance increase.
    This adds a Database#find_by_table_column_value method that uses
    a given literal table and column, and a value argument, and returns
    the first matching row (with all columns) for that table.  The value
    argument is literalized, but the table and column are used as is,
    so you cannot use untrusted input for those arguments.
    If a model is a optimizable (single primary key, single table),
    find_by_table_column_value is used instead of the usual lookup using
    primary_key_hash.  Unfortunately, it wasn't easy to determine which
    models are optimizable.  Checking all of the dataset options for the
    model dataset is too likely to break in future versions, even if I
    did get it correct in this version.  I took the conservative approach
    and made it so that the model is optimizable if a symbol is passed to
    set_dataset. So the following models will use the optimization:
      class Foo < Sequel::Model
        # Using the implicit table is optimized
      class Foo < Sequel::Model(:foos)
        # Since you provide a Symbol to Model(), it is optimized
      class Foo < Sequel::Model
       set_dataset :foos
       # Symbol provided to set_dataset is optimized
    But the following otherwise equivalent models are not optimized:
      class Foo < Sequel::Model(Model.db[:foos])
      class Foo < Sequel::Model
       set_dataset db[:foos]
    To make this as fast as possible, two class instance variables are
    added to model: @simple_pk and @simple_table.  They store the
    already literalized table and primary key column names, which are
    passed to find_by_table_column_value.
    This commit also adds some specs for the previous optimization
    commit, to bring code coverage back to 100%.
    committed Feb 22, 2009
  2. Make Dataset#literal call methods like #literal_string, override less…

    … in adapters, for a 20-25% performance increase
    Profiling shows Dataset#literal can take around 10% total time, so
    this is probably only a 2% performance increase in general.
    Basically, this changes how the adapters override the default
    literalization.  Instead of overriding literal and using a case
    statement and super in the else clause, they override literal_*
    methods, so the default Dataset#literal is always called.  In
    addition to being faster the code is noticeably cleaner as well.
    During this change I finally decided to change the Sequel default
    date and timestamp formats from the SQL standard (e.g.
    "TIMESTAMP 'YYYY-MM-DD HH:MM:SS'") to the defacto ISO8601 standard used
    by most of the adatpers.  I'm pretty sure this won't break existing
    code, but testing on most adapters would be nice, especially on
    the Firebird and ODBC adapters.
    This commit also moves the unsupported.rb and stored_procedures.rb
    from lib/sequel_core/dataset to lib/sequel_core/adapters/utils, since
    they are only used by certain adapters.  One of the results of this
    is that Sequel::Dataset::UnsupportedExceptIntersect(All)? is not
    guaranteed to be defined.
    From my profiling, it appears that another 10% increase to
    Dataset#literal could be achieved by adding a #to_sequel_literal
    method to all objects, and calling that instead of using a case
    statement.  At this point, that's not a road I want to go down.
    committed Feb 22, 2009
Commits on Feb 20, 2009
  1. Another minor README fix

    committed Feb 20, 2009
Commits on Feb 19, 2009
  1. Make PostgreSQL and Firebird adapters send inserts to the master serv…

    …er instead of the slave server by default
    The PostgreSQL (if it is connecting to a 8.2 or greater database) and
    Firebird adapters use INSERT RETURNING to return data directly from
    the INSERT query.  Because of that, the INSERT query is treated as a
    SELECT by Sequel.  Since it is treated as a select, the request went
    to the slave servers instead of the master.  Fix this by setting the
    server to use to the master (:default) server unless it is already
    set to use a different server.
    To easily implement this, add Dataset#default_server_opts private
    This comment also removes pointless execute_insert definitions some
    adapters, since they just duplicated the now default definition.
    committed Feb 19, 2009
  2. Avoid the internal use of Symbol#*, refactor Database#locks in the Po…

    …stgreSQL shared adapter
    committed Feb 19, 2009
  3. Use before_update instead of before_save when caching and remove cach…

    This breaks backward compatibility slightly, but it's unlikely anyone
    else was using cache_delete_unless_new.
    committed Feb 19, 2009
  4. Make Dataset#select, #select_more, and #get take a block that yields …

    …a SQL::VirtualRow, similar to #filter
    This is useful for select just like it is useful for filter, in that
    it allows a nicer API in the case where you can't use the Symbol
    shortcuts for methods (either because you are running on Ruby 1.9 or
    because another library defines them).  So instead of:
    you can do:
 {|o| o.prettify(:name)}
    This commit also changes some of the dataset convenience methods to
    use this new feature.
    committed Feb 19, 2009
Commits on Feb 17, 2009
Commits on Feb 16, 2009
Commits on Feb 11, 2009
  1. Add :conditions association option, for easier filtering of associate…

    …d objects
    This commit like the previous one doesn't allow anything that wasn't
    possible before, but should make the API nicer.  Before, if you
    wanted to filter associated records and cover all cases, you had to
    specify a block and the :graph_conditions option.  Now, assuming
    that your condition is expressible as a hash or array of two pairs,
    you can just change :graph_conditions to :conditions and eliminate
    the block.  You can change this:
      one_to_many :japanese_verses, :class=>:Verse,
       :graph_conditions=>{:languageid=>3} do |ds|
      one_to_many :japanese_verses, :class=>:Verse,\
    committed Feb 11, 2009
  2. Add :clone association option, for making clones of existing associat…

    While Sequel makes it easy to get the dataset representing the
    association via the association_dataset method, I recommend using a
    separate association if you are doing the same thing with
    association_dataset in multiple places.  This adds a shortcut to make
    that easier, by allowing you to clone an existing association's
    options.  This is especially helpful when dealing with legacy schemas
    were you would have to specify many of the same options for each
    Here's an example use:
      many_to_many :deputies, :class=>:Employee, \
       :join_table=>:employeecurrentaudits, :left_key=>:currentauditid, \
       :right_key=>:employeeid, :order=>[:firstname, :lastname] do |ds|
      many_to_many :project_managers, :clone=>:deputies do |ds|
      many_to_many :team_leaders, :clone=>:deputies do |ds|
    Before, to do something like this, you would have had to specify
    the :join_table, :left_key, :right_key, and :class options in each
    association.  Also, though this example doesn't show it, the cloned
    association's block is copied as well if the current association
    doesn't use a block.  You can use the :block=>nil option to not
    clone the previous block and not use a block for the current
    committed Feb 11, 2009
  3. Handle typecasting invalid date strings (and possible other types) co…

    Before, Database#typecast_value would rescue ArgumentErrors for the
    :integer and :float types, but not other types.  This commit changes
    it to rescue ArgumentError for any type, change it to
    Error::InvalidValue, and reraise keeping the same backtrace.
    committed Feb 11, 2009
Commits on Feb 9, 2009
  1. Clean up tmm1's MySQL patches

    This updates the documentation for the MySQL adapter's
    Database#connect and the CHANGELOG, and makes the
    SQL_AUTO_IS_NULL=0 optional.
    committed Feb 9, 2009
Commits on Feb 7, 2009