sequel 3.24.1 → 3.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +28 -0
 - data/doc/association_basics.rdoc +3 -3
 - data/doc/dataset_basics.rdoc +4 -4
 - data/doc/migration.rdoc +6 -5
 - data/doc/opening_databases.rdoc +8 -5
 - data/doc/release_notes/3.25.0.txt +88 -0
 - data/lib/sequel/adapters/jdbc.rb +2 -2
 - data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
 - data/lib/sequel/adapters/shared/postgres.rb +0 -5
 - data/lib/sequel/adapters/tinytds.rb +1 -2
 - data/lib/sequel/database/schema_generator.rb +6 -4
 - data/lib/sequel/database/schema_methods.rb +17 -6
 - data/lib/sequel/dataset.rb +8 -0
 - data/lib/sequel/dataset/misc.rb +0 -9
 - data/lib/sequel/dataset/query.rb +80 -21
 - data/lib/sequel/extensions/migration.rb +1 -1
 - data/lib/sequel/model/base.rb +15 -6
 - data/lib/sequel/model/errors.rb +1 -1
 - data/lib/sequel/plugins/association_pks.rb +16 -0
 - data/lib/sequel/plugins/update_primary_key.rb +1 -1
 - data/lib/sequel/version.rb +2 -2
 - data/spec/adapters/mysql_spec.rb +7 -0
 - data/spec/core/database_spec.rb +0 -295
 - data/spec/core/dataset_spec.rb +70 -1
 - data/spec/core/expression_filters_spec.rb +39 -0
 - data/spec/core/schema_spec.rb +304 -0
 - data/spec/core/spec_helper.rb +29 -0
 - data/spec/extensions/association_pks_spec.rb +31 -0
 - data/spec/extensions/schema_spec.rb +12 -20
 - data/spec/integration/dataset_test.rb +17 -0
 - data/spec/integration/prepared_statement_test.rb +15 -0
 - data/spec/model/model_spec.rb +60 -0
 - data/spec/model/plugins_spec.rb +17 -0
 - data/spec/model/validations_spec.rb +11 -0
 - metadata +7 -5
 
    
        data/CHANGELOG
    CHANGED
    
    | 
         @@ -1,3 +1,31 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            === 3.25.0 (2011-07-01)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            * Work with tiny_tds-0.4.5 in the tinytds adapter, older versions are no longer supported (jeremyevans)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            * Make association_pks plugin typecast provided values to integer if the primary key column type is integer (jeremyevans)
         
     | 
| 
      
 6 
     | 
    
         
            +
             
         
     | 
| 
      
 7 
     | 
    
         
            +
            * Model.set_dataset now accepts Identifier, QualifiedIdentifier, and AliasedExpression arguments (jeremyevans)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            * Fix handling of nil values in bound variables and prepared statement and stored procedure arguments in the jdbc adapter (jeremyevans, wei)
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            * Allow treating Datasets as Expressions, e.g. DB[:table1].select(:column1) > DB[:table2].select(:column2) (jeremyevans)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            * No longer use CASCADE by default when dropping tables on PostgreSQL (jeremyevans)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            * Support :cascade option to #drop_table, #drop_view, #drop_column, and #drop_constraint for using CASCADE (jeremyevans)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            * If validation error messages are LiteralStrings, don't add the column name to them in Errors#full_messages (jeremyevans)
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            * Fix bug loading plugins on 1.9 where ::ClassMethods, ::InstanceMethods, or ::DatasetMethods is defined (jeremyevans)
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            * Add Dataset#exclude_where and Dataset#exclude_having methods, so you can force use of having or where clause (jeremyevans)
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            * Allow Dataset#select_all to take table name arguments and select all columns from each given table (jeremyevans)
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            * Add Dataset#select_group method, for selecting and grouping on the same columns (jeremyevans)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            * Allow Dataset#group and Dataset#group_and_count to accept a virtual row block (jeremyevans)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
       1 
29 
     | 
    
         
             
            === 3.24.1 (2011-06-03)
         
     | 
| 
       2 
30 
     | 
    
         | 
| 
       3 
31 
     | 
    
         
             
            * Ignore index creation errors if using create_table? with the IF NOT EXISTS syntax (jeremyevans) (#362)
         
     | 
    
        data/doc/association_basics.rdoc
    CHANGED
    
    | 
         @@ -247,7 +247,7 @@ example is a tree structure: 
     | 
|
| 
       247 
247 
     | 
    
         | 
| 
       248 
248 
     | 
    
         
             
              class Node
         
     | 
| 
       249 
249 
     | 
    
         
             
                many_to_one :parent, :class=>self
         
     | 
| 
       250 
     | 
    
         
            -
                one_to_many :children :key=>:parent_id, :class=>self
         
     | 
| 
      
 250 
     | 
    
         
            +
                one_to_many :children, :key=>:parent_id, :class=>self
         
     | 
| 
       251 
251 
     | 
    
         
             
              end
         
     | 
| 
       252 
252 
     | 
    
         | 
| 
       253 
253 
     | 
    
         
             
            For many_to_many self_referential associations, it's fairly similar.  Here's
         
     | 
| 
         @@ -381,7 +381,7 @@ method, you have to pass a proc as an argument: 
     | 
|
| 
       381 
381 
     | 
    
         
             
            == Filtering By Associations
         
     | 
| 
       382 
382 
     | 
    
         | 
| 
       383 
383 
     | 
    
         
             
            In addition to using the association method to get associated objects, you
         
     | 
| 
       384 
     | 
    
         
            -
            can also use associated objects in filters.  For example,  
     | 
| 
      
 384 
     | 
    
         
            +
            can also use associated objects in filters.  For example, to get
         
     | 
| 
       385 
385 
     | 
    
         
             
            all albums for a given artist, you would usually do:
         
     | 
| 
       386 
386 
     | 
    
         | 
| 
       387 
387 
     | 
    
         
             
              @artist.albums
         
     | 
| 
         @@ -479,7 +479,7 @@ would be bad association names. 
     | 
|
| 
       479 
479 
     | 
    
         | 
| 
       480 
480 
     | 
    
         
             
            == Database Schema
         
     | 
| 
       481 
481 
     | 
    
         | 
| 
       482 
     | 
    
         
            -
            Creating an association 
     | 
| 
      
 482 
     | 
    
         
            +
            Creating an association doesn't modify the database schema.  Sequel
         
     | 
| 
       483 
483 
     | 
    
         
             
            assumes your associations reflect the existing database schema.  If not,
         
     | 
| 
       484 
484 
     | 
    
         
             
            you should modify your schema before creating the associations.
         
     | 
| 
       485 
485 
     | 
    
         | 
    
        data/doc/dataset_basics.rdoc
    CHANGED
    
    | 
         @@ -74,12 +74,12 @@ Most Dataset methods that users will use can be broken down into two types: 
     | 
|
| 
       74 
74 
     | 
    
         | 
| 
       75 
75 
     | 
    
         
             
            Most dataset methods fall into this category, which can be further broken down by the clause they affect:
         
     | 
| 
       76 
76 
     | 
    
         | 
| 
       77 
     | 
    
         
            -
            SELECT:: select, select_all, select_append, select_more
         
     | 
| 
      
 77 
     | 
    
         
            +
            SELECT:: select, select_all, select_append, select_group, select_more
         
     | 
| 
       78 
78 
     | 
    
         
             
            FROM:: from, from_self
         
     | 
| 
       79 
79 
     | 
    
         
             
            JOIN:: join, left_join, right_join, full_join, natural_join, natural_left_join, natural_right_join, natural_full_join, cross_join, inner_join, left_outer_join, right_outer_join, full_outer_join, join_table
         
     | 
| 
       80 
     | 
    
         
            -
            WHERE:: where, filter, exclude, and, or, grep, invert, unfiltered
         
     | 
| 
       81 
     | 
    
         
            -
            GROUP:: group, group_by, group_and_count, ungrouped
         
     | 
| 
       82 
     | 
    
         
            -
            HAVING:: having, filter, exclude, and, or, grep, invert, unfiltered
         
     | 
| 
      
 80 
     | 
    
         
            +
            WHERE:: where, filter, exclude, exclude_where, and, or, grep, invert, unfiltered
         
     | 
| 
      
 81 
     | 
    
         
            +
            GROUP:: group, group_by, group_and_count, select_group, ungrouped
         
     | 
| 
      
 82 
     | 
    
         
            +
            HAVING:: having, filter, exclude, exclude_having, and, or, grep, invert, unfiltered
         
     | 
| 
       83 
83 
     | 
    
         
             
            ORDER:: order, order_by, order_append, order_prepend, order_more, reverse, reverse_order, unordered
         
     | 
| 
       84 
84 
     | 
    
         
             
            LIMIT:: limit, unlimited
         
     | 
| 
       85 
85 
     | 
    
         
             
            compounds:: union, intersect, except
         
     | 
    
        data/doc/migration.rdoc
    CHANGED
    
    | 
         @@ -117,7 +117,8 @@ This looks a little weird, but you need to be aware that inside an up or +down+ 
     | 
|
| 
       117 
117 
     | 
    
         
             
            self always refers to the <tt>Sequel::Database</tt> object that the migration is being applied to.
         
     | 
| 
       118 
118 
     | 
    
         
             
            Since <tt>Database#[]</tt> creates datasets, using <tt>self[:artists]</tt> inside the +up+ block creates
         
     | 
| 
       119 
119 
     | 
    
         
             
            a dataset on the database representing all columns in the +artists+ table, and updates it to set the
         
     | 
| 
       120 
     | 
    
         
            -
            +location+ column to <tt>'Sacramento'</tt>.
         
     | 
| 
      
 120 
     | 
    
         
            +
            +location+ column to <tt>'Sacramento'</tt>.  You should avoid referencing the <tt>Sequel::Database</tt>
         
     | 
| 
      
 121 
     | 
    
         
            +
            object directly in your migration, and always use self to reference it, otherwise you may run into problems.
         
     | 
| 
       121 
122 
     | 
    
         | 
| 
       122 
123 
     | 
    
         
             
            It is possible to use model classes inside migrations, as long as they are loaded into the ruby interpreter,
         
     | 
| 
       123 
124 
     | 
    
         
             
            but it's a bad habit as changes to your model classes can then break old migrations, and this breakage is
         
     | 
| 
         @@ -897,8 +898,8 @@ artist per album to multiple artists per album: 
     | 
|
| 
       897 
898 
     | 
    
         
             
                  # Insert one row in the albums_artists table
         
     | 
| 
       898 
899 
     | 
    
         
             
                  # for each row in the albums table where there
         
     | 
| 
       899 
900 
     | 
    
         
             
                  # is an associated artist
         
     | 
| 
       900 
     | 
    
         
            -
                   
     | 
| 
       901 
     | 
    
         
            -
                    
     | 
| 
      
 901 
     | 
    
         
            +
                  self[:albums_artists].insert([:album_id, :artist_id],
         
     | 
| 
      
 902 
     | 
    
         
            +
                   self[:albums].select(:id, :artist_id).exclude(:artist_id=>nil))
         
     | 
| 
       902 
903 
     | 
    
         | 
| 
       903 
904 
     | 
    
         
             
                  # Drop the now unnecesssary column from the albums table
         
     | 
| 
       904 
905 
     | 
    
         
             
                  drop_column :albums, :artist_id
         
     | 
| 
         @@ -910,12 +911,12 @@ artist per album to multiple artists per album: 
     | 
|
| 
       910 
911 
     | 
    
         
             
                  # If possible, associate each album with one of the artists
         
     | 
| 
       911 
912 
     | 
    
         
             
                  # it was associated with.  This loses information, but
         
     | 
| 
       912 
913 
     | 
    
         
             
                  # there's no way around that.
         
     | 
| 
       913 
     | 
    
         
            -
                   
     | 
| 
      
 914 
     | 
    
         
            +
                  self[:albums_artists].
         
     | 
| 
       914 
915 
     | 
    
         
             
                   group(:album_id).
         
     | 
| 
       915 
916 
     | 
    
         
             
                   select{[album_id, max(artist_id).as(artist_id)]}.
         
     | 
| 
       916 
917 
     | 
    
         
             
                   having{artist_id >  0}.
         
     | 
| 
       917 
918 
     | 
    
         
             
                   all do |r|
         
     | 
| 
       918 
     | 
    
         
            -
                      
     | 
| 
      
 919 
     | 
    
         
            +
                     self[:artists].
         
     | 
| 
       919 
920 
     | 
    
         
             
                      filter(:id=>r[:album_id]).
         
     | 
| 
       920 
921 
     | 
    
         
             
                      update(:artist_id=>r[:artist_id])
         
     | 
| 
       921 
922 
     | 
    
         
             
                   end
         
     | 
    
        data/doc/opening_databases.rdoc
    CHANGED
    
    | 
         @@ -355,14 +355,17 @@ Examples: 
     | 
|
| 
       355 
355 
     | 
    
         | 
| 
       356 
356 
     | 
    
         
             
            Because the underscore is not a valid character in a URI schema, the adapter
         
     | 
| 
       357 
357 
     | 
    
         
             
            is named tinytds instead of tiny_tds.  The connection options are passed directly
         
     | 
| 
       358 
     | 
    
         
            -
            to tiny_tds, except that the tiny_tds : 
     | 
| 
       359 
     | 
    
         
            -
            the Sequel : 
     | 
| 
       360 
     | 
    
         
            -
             
     | 
| 
       361 
     | 
    
         
            -
             
     | 
| 
       362 
     | 
    
         
            -
            : 
     | 
| 
      
 358 
     | 
    
         
            +
            to tiny_tds, except that the tiny_tds :username option is set to
         
     | 
| 
      
 359 
     | 
    
         
            +
            the Sequel :user option.  If you want to use an entry in the freetds.conf file, you
         
     | 
| 
      
 360 
     | 
    
         
            +
            should specify the :dataserver option with that name as the value.  Some other
         
     | 
| 
      
 361 
     | 
    
         
            +
            options that you may want to set are :login_timeout, :timeout, :tds_version, :azure,
         
     | 
| 
      
 362 
     | 
    
         
            +
            :appname, and :encoding, see the tiny_tds README for details.
         
     | 
| 
      
 363 
     | 
    
         
            +
             
     | 
| 
       363 
364 
     | 
    
         
             
            For highest performance, you should disable any identifier output method when
         
     | 
| 
       364 
365 
     | 
    
         
             
            using the tinytds adapter, which probably means disabling any identifier input method
         
     | 
| 
       365 
366 
     | 
    
         
             
            as well.  The default for Microsoft SQL Server is to :downcase identifiers on output
         
     | 
| 
       366 
367 
     | 
    
         
             
            and :upcase them on input, so the highest performance will require changing the setting
         
     | 
| 
       367 
368 
     | 
    
         
             
            from the default.
         
     | 
| 
       368 
369 
     | 
    
         | 
| 
      
 370 
     | 
    
         
            +
            The Sequel tinytds adapter requires tiny_tds >= 0.4.5, and if you are using FreeTDS
         
     | 
| 
      
 371 
     | 
    
         
            +
            0.91, you must at least be using 0.91rc2 (0.91rc1 does not work).
         
     | 
| 
         @@ -0,0 +1,88 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            = New Features
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            * drop_table, drop_view, drop_column, and drop_constraint all now
         
     | 
| 
      
 4 
     | 
    
         
            +
              support a :cascade option for using CASCADE.
         
     | 
| 
      
 5 
     | 
    
         
            +
              
         
     | 
| 
      
 6 
     | 
    
         
            +
                DB.drop_table(:tab, :cascade=>true)
         
     | 
| 
      
 7 
     | 
    
         
            +
                # DROP TABLE tab CASCADE
         
     | 
| 
      
 8 
     | 
    
         
            +
                
         
     | 
| 
      
 9 
     | 
    
         
            +
                DB.drop_column(:tab, :col, :cascade=>true)
         
     | 
| 
      
 10 
     | 
    
         
            +
                # ALTER TABLE tab DROP COLUMN col CASCADE
         
     | 
| 
      
 11 
     | 
    
         
            +
                
         
     | 
| 
      
 12 
     | 
    
         
            +
              A few databases support CASCADE for dropping tables and views,
         
     | 
| 
      
 13 
     | 
    
         
            +
              but only PostgreSQL appears to support it for columns and
         
     | 
| 
      
 14 
     | 
    
         
            +
              constraints.  Using the :cascade option when the underlying
         
     | 
| 
      
 15 
     | 
    
         
            +
              database doesn't support it will probably result in a
         
     | 
| 
      
 16 
     | 
    
         
            +
              DatabaseError being raised.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            * You can now use datasets as expressions, allowing things such as:
         
     | 
| 
      
 19 
     | 
    
         
            +
              
         
     | 
| 
      
 20 
     | 
    
         
            +
                DB[:table1].select(:column1) > DB[:table2].select(:column2)
         
     | 
| 
      
 21 
     | 
    
         
            +
                # (SELECT column1 FROM table1) > (SELECT column2 FROM table2)
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                DB[:table1].select(:column1).cast(Integer)
         
     | 
| 
      
 24 
     | 
    
         
            +
                # CAST((SELECT column1 FROM table1) AS integer)
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            * Dataset#select_group has been added for grouping and selecting on
         
     | 
| 
      
 27 
     | 
    
         
            +
              the same columns.
         
     | 
| 
      
 28 
     | 
    
         
            +
              
         
     | 
| 
      
 29 
     | 
    
         
            +
                DB[:a].select_group(:b, :c)
         
     | 
| 
      
 30 
     | 
    
         
            +
                # SELECT b, c FROM a GROUP BY b, c
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            * Dataset#exclude_where and #exclude_having methods have been added,
         
     | 
| 
      
 33 
     | 
    
         
            +
              allowing you to specify which clause to affect.  #exclude's
         
     | 
| 
      
 34 
     | 
    
         
            +
              behavior is still to add to the HAVING clause if one is present,
         
     | 
| 
      
 35 
     | 
    
         
            +
              and use the WHERE clause otherwise.
         
     | 
| 
      
 36 
     | 
    
         
            +
              
         
     | 
| 
      
 37 
     | 
    
         
            +
            * Dataset#select_all now accepts optional arguments and will select
         
     | 
| 
      
 38 
     | 
    
         
            +
              all columns from those arguments if present:
         
     | 
| 
      
 39 
     | 
    
         
            +
              
         
     | 
| 
      
 40 
     | 
    
         
            +
                DB[:a].select_all(:a)
         
     | 
| 
      
 41 
     | 
    
         
            +
                # SELECT a.* FROM a
         
     | 
| 
      
 42 
     | 
    
         
            +
                
         
     | 
| 
      
 43 
     | 
    
         
            +
                DB.from(:a, :b).select_all(:a, :b)
         
     | 
| 
      
 44 
     | 
    
         
            +
                # SELECT a.*, b.* FROM a, b
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            * Dataset#group and #group_and_count now both accept virtual row
         
     | 
| 
      
 47 
     | 
    
         
            +
              blocks:
         
     | 
| 
      
 48 
     | 
    
         
            +
              
         
     | 
| 
      
 49 
     | 
    
         
            +
                DB[:a].select(:b).group{c(d)}
         
     | 
| 
      
 50 
     | 
    
         
            +
                # SELECT b FROM a GROUP BY c(d)
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            * If you use a LiteralString as a validation error message, 
         
     | 
| 
      
 53 
     | 
    
         
            +
              Errors#full_messages will now not add the related column name to
         
     | 
| 
      
 54 
     | 
    
         
            +
              the start of the error message.
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            * Model.set_dataset now accepts SQL::Identifier,
         
     | 
| 
      
 57 
     | 
    
         
            +
              SQL::QualifiedIdentifier, and SQL::AliasedExpression instances,
         
     | 
| 
      
 58 
     | 
    
         
            +
              treating them like Symbols.
         
     | 
| 
      
 59 
     | 
    
         
            +
              
         
     | 
| 
      
 60 
     | 
    
         
            +
            = Other Improvements
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            * The association_pks plugin's setter method will now automatically
         
     | 
| 
      
 63 
     | 
    
         
            +
              convert a given array of strings to an array of integers if the
         
     | 
| 
      
 64 
     | 
    
         
            +
              primary key field is an integer field, which should make it easier
         
     | 
| 
      
 65 
     | 
    
         
            +
              to use in web applications.
         
     | 
| 
      
 66 
     | 
    
         
            +
              
         
     | 
| 
      
 67 
     | 
    
         
            +
            * nil bound variable, prepared statement, and stored procedure
         
     | 
| 
      
 68 
     | 
    
         
            +
              arguments are now handled correctly in the JDBC adapter.
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            * On 1.9, you can now load plugins even when ::ClassMethods,
         
     | 
| 
      
 71 
     | 
    
         
            +
              ::InstanceMethods, or ::DatasetMethods is defined.
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            = Backwards Compatibility
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            * The tinytds adapter now only works with tiny_tds 0.4.5 and greater.
         
     | 
| 
      
 76 
     | 
    
         
            +
              Also, if you were using the tinytds adapter with FreeTDS 0.91rc1,
         
     | 
| 
      
 77 
     | 
    
         
            +
              you need to upgrade to FreeTDS 0.91rc2 for it to work.  Also, if
         
     | 
| 
      
 78 
     | 
    
         
            +
              you were referencing an entry in the freetds.conf file, you now
         
     | 
| 
      
 79 
     | 
    
         
            +
              need to specify it directly using the :dataserver option when
         
     | 
| 
      
 80 
     | 
    
         
            +
              connecting, the adapter no longer copies the :host option to the
         
     | 
| 
      
 81 
     | 
    
         
            +
              :dataserver option.
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            * On postgresql, Sequel now no longer drops tables with CASCADE by
         
     | 
| 
      
 84 
     | 
    
         
            +
              default.  You now have to use the :cascade option to drop_table if
         
     | 
| 
      
 85 
     | 
    
         
            +
              you want to use CASCADE.
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            * The Database#drop_table_sql private method now takes an additional
         
     | 
| 
      
 88 
     | 
    
         
            +
              options hash argument.
         
     | 
    
        data/lib/sequel/adapters/jdbc.rb
    CHANGED
    
    | 
         @@ -422,8 +422,8 @@ module Sequel 
     | 
|
| 
       422 
422 
     | 
    
         
             
                      cps.setDouble(i, arg)
         
     | 
| 
       423 
423 
     | 
    
         
             
                    when TrueClass, FalseClass
         
     | 
| 
       424 
424 
     | 
    
         
             
                      cps.setBoolean(i, arg)
         
     | 
| 
       425 
     | 
    
         
            -
                    when  
     | 
| 
       426 
     | 
    
         
            -
                      cps. 
     | 
| 
      
 425 
     | 
    
         
            +
                    when NilClass
         
     | 
| 
      
 426 
     | 
    
         
            +
                      cps.setString(i, nil)
         
     | 
| 
       427 
427 
     | 
    
         
             
                    when DateTime
         
     | 
| 
       428 
428 
     | 
    
         
             
                      cps.setTimestamp(i, java_sql_datetime(arg))
         
     | 
| 
       429 
429 
     | 
    
         
             
                    when Date
         
     | 
| 
         @@ -60,6 +60,12 @@ module Sequel 
     | 
|
| 
       60 
60 
     | 
    
         | 
| 
       61 
61 
     | 
    
         
             
                    private
         
     | 
| 
       62 
62 
     | 
    
         | 
| 
      
 63 
     | 
    
         
            +
                    # Use setNull for nil arguments as the default behavior of setString
         
     | 
| 
      
 64 
     | 
    
         
            +
                    # with nil doesn't appear to work correctly on PostgreSQL.
         
     | 
| 
      
 65 
     | 
    
         
            +
                    def set_ps_arg(cps, arg, i)
         
     | 
| 
      
 66 
     | 
    
         
            +
                      arg.nil? ? cps.setNull(i, JavaSQL::Types::NULL) : super
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
       63 
69 
     | 
    
         
             
                    # Extend the adapter with the JDBC PostgreSQL AdapterMethods
         
     | 
| 
       64 
70 
     | 
    
         
             
                    def setup_connection(conn)
         
     | 
| 
       65 
71 
     | 
    
         
             
                      conn = super(conn)
         
     | 
| 
         @@ -460,11 +460,6 @@ module Sequel 
     | 
|
| 
       460 
460 
     | 
    
         
             
                    "DROP LANGUAGE#{' IF EXISTS' if opts[:if_exists]} #{name}#{' CASCADE' if opts[:cascade]}"
         
     | 
| 
       461 
461 
     | 
    
         
             
                  end
         
     | 
| 
       462 
462 
     | 
    
         | 
| 
       463 
     | 
    
         
            -
                  # Always CASCADE the table drop
         
     | 
| 
       464 
     | 
    
         
            -
                  def drop_table_sql(name)
         
     | 
| 
       465 
     | 
    
         
            -
                    "DROP TABLE #{quote_schema_table(name)} CASCADE"
         
     | 
| 
       466 
     | 
    
         
            -
                  end
         
     | 
| 
       467 
     | 
    
         
            -
                  
         
     | 
| 
       468 
463 
     | 
    
         
             
                  # SQL for dropping a trigger from the database.
         
     | 
| 
       469 
464 
     | 
    
         
             
                  def drop_trigger_sql(table, name, opts={})
         
     | 
| 
       470 
465 
     | 
    
         
             
                    "DROP TRIGGER#{' IF EXISTS' if opts[:if_exists]} #{name} ON #{quote_schema_table(table)}#{' CASCADE' if opts[:cascade]}"
         
     | 
| 
         @@ -11,7 +11,6 @@ module Sequel 
     | 
|
| 
       11 
11 
     | 
    
         
             
                  # :dataserver and :username options.
         
     | 
| 
       12 
12 
     | 
    
         
             
                  def connect(server)
         
     | 
| 
       13 
13 
     | 
    
         
             
                    opts = server_opts(server)
         
     | 
| 
       14 
     | 
    
         
            -
                    opts[:dataserver] = opts[:host]
         
     | 
| 
       15 
14 
     | 
    
         
             
                    opts[:username] = opts[:user]
         
     | 
| 
       16 
15 
     | 
    
         
             
                    set_mssql_unicode_strings
         
     | 
| 
       17 
16 
     | 
    
         
             
                    TinyTds::Client.new(opts)
         
     | 
| 
         @@ -39,7 +38,7 @@ module Sequel 
     | 
|
| 
       39 
38 
     | 
    
         
             
                        end
         
     | 
| 
       40 
39 
     | 
    
         
             
                        yield(r) if block_given?
         
     | 
| 
       41 
40 
     | 
    
         
             
                      rescue TinyTds::Error => e
         
     | 
| 
       42 
     | 
    
         
            -
                        raise_error(e, :disconnect 
     | 
| 
      
 41 
     | 
    
         
            +
                        raise_error(e, :disconnect=>!c.active?)
         
     | 
| 
       43 
42 
     | 
    
         
             
                      ensure
         
     | 
| 
       44 
43 
     | 
    
         
             
                       r.cancel if r && c.sqlsent?
         
     | 
| 
       45 
44 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -329,15 +329,17 @@ module Sequel 
     | 
|
| 
       329 
329 
     | 
    
         
             
                  # Remove a column from the DDL for the table.
         
     | 
| 
       330 
330 
     | 
    
         
             
                  #
         
     | 
| 
       331 
331 
     | 
    
         
             
                  #   drop_column(:artist_id) # DROP COLUMN artist_id
         
     | 
| 
       332 
     | 
    
         
            -
                   
     | 
| 
       333 
     | 
    
         
            -
             
     | 
| 
      
 332 
     | 
    
         
            +
                  #   drop_column(:artist_id, :cascade=>true) # DROP COLUMN artist_id CASCADE
         
     | 
| 
      
 333 
     | 
    
         
            +
                  def drop_column(name, opts={})
         
     | 
| 
      
 334 
     | 
    
         
            +
                    @operations << {:op => :drop_column, :name => name}.merge(opts)
         
     | 
| 
       334 
335 
     | 
    
         
             
                  end
         
     | 
| 
       335 
336 
     | 
    
         | 
| 
       336 
337 
     | 
    
         
             
                  # Remove a constraint from the DDL for the table.
         
     | 
| 
       337 
338 
     | 
    
         
             
                  #
         
     | 
| 
       338 
339 
     | 
    
         
             
                  #   drop_constraint(:unique_name) # DROP CONSTRAINT unique_name
         
     | 
| 
       339 
     | 
    
         
            -
                   
     | 
| 
       340 
     | 
    
         
            -
             
     | 
| 
      
 340 
     | 
    
         
            +
                  #   drop_constraint(:unique_name, :cascade=>true) # DROP CONSTRAINT unique_name CASCADE
         
     | 
| 
      
 341 
     | 
    
         
            +
                  def drop_constraint(name, opts={})
         
     | 
| 
      
 342 
     | 
    
         
            +
                    @operations << {:op => :drop_constraint, :name => name}.merge(opts)
         
     | 
| 
       341 
343 
     | 
    
         
             
                  end
         
     | 
| 
       342 
344 
     | 
    
         | 
| 
       343 
345 
     | 
    
         
             
                  # Remove an index from the DDL for the table.
         
     | 
| 
         @@ -159,10 +159,13 @@ module Sequel 
     | 
|
| 
       159 
159 
     | 
    
         | 
| 
       160 
160 
     | 
    
         
             
                # Drops one or more tables corresponding to the given names:
         
     | 
| 
       161 
161 
     | 
    
         
             
                #
         
     | 
| 
      
 162 
     | 
    
         
            +
                #   DB.drop_table(:posts)
         
     | 
| 
       162 
163 
     | 
    
         
             
                #   DB.drop_table(:posts, :comments)
         
     | 
| 
      
 164 
     | 
    
         
            +
                #   DB.drop_table(:posts, :comments, :cascade=>true)
         
     | 
| 
       163 
165 
     | 
    
         
             
                def drop_table(*names)
         
     | 
| 
      
 166 
     | 
    
         
            +
                  options = names.last.is_a?(Hash) ? names.pop : {}
         
     | 
| 
       164 
167 
     | 
    
         
             
                  names.each do |n|
         
     | 
| 
       165 
     | 
    
         
            -
                    execute_ddl(drop_table_sql(n))
         
     | 
| 
      
 168 
     | 
    
         
            +
                    execute_ddl(drop_table_sql(n, options))
         
     | 
| 
       166 
169 
     | 
    
         
             
                    remove_cached_schema(n)
         
     | 
| 
       167 
170 
     | 
    
         
             
                  end
         
     | 
| 
       168 
171 
     | 
    
         
             
                  nil
         
     | 
| 
         @@ -171,9 +174,12 @@ module Sequel 
     | 
|
| 
       171 
174 
     | 
    
         
             
                # Drops one or more views corresponding to the given names:
         
     | 
| 
       172 
175 
     | 
    
         
             
                #
         
     | 
| 
       173 
176 
     | 
    
         
             
                #   DB.drop_view(:cheap_items)
         
     | 
| 
      
 177 
     | 
    
         
            +
                #   DB.drop_view(:cheap_items, :pricey_items)
         
     | 
| 
      
 178 
     | 
    
         
            +
                #   DB.drop_view(:cheap_items, :pricey_items, :cascade=>true)
         
     | 
| 
       174 
179 
     | 
    
         
             
                def drop_view(*names)
         
     | 
| 
      
 180 
     | 
    
         
            +
                  options = names.last.is_a?(Hash) ? names.pop : {}
         
     | 
| 
       175 
181 
     | 
    
         
             
                  names.each do |n|
         
     | 
| 
       176 
     | 
    
         
            -
                    execute_ddl( 
     | 
| 
      
 182 
     | 
    
         
            +
                    execute_ddl(drop_view_sql(n, options))
         
     | 
| 
       177 
183 
     | 
    
         
             
                    remove_cached_schema(n)
         
     | 
| 
       178 
184 
     | 
    
         
             
                  end
         
     | 
| 
       179 
185 
     | 
    
         
             
                  nil
         
     | 
| 
         @@ -228,7 +234,7 @@ module Sequel 
     | 
|
| 
       228 
234 
     | 
    
         
             
                  when :add_column
         
     | 
| 
       229 
235 
     | 
    
         
             
                    "ADD COLUMN #{column_definition_sql(op)}"
         
     | 
| 
       230 
236 
     | 
    
         
             
                  when :drop_column
         
     | 
| 
       231 
     | 
    
         
            -
                    "DROP COLUMN #{quoted_name}"
         
     | 
| 
      
 237 
     | 
    
         
            +
                    "DROP COLUMN #{quoted_name}#{' CASCADE' if op[:cascade]}"
         
     | 
| 
       232 
238 
     | 
    
         
             
                  when :rename_column
         
     | 
| 
       233 
239 
     | 
    
         
             
                    "RENAME COLUMN #{quoted_name} TO #{quote_identifier(op[:new_name])}"
         
     | 
| 
       234 
240 
     | 
    
         
             
                  when :set_column_type
         
     | 
| 
         @@ -244,7 +250,7 @@ module Sequel 
     | 
|
| 
       244 
250 
     | 
    
         
             
                  when :add_constraint
         
     | 
| 
       245 
251 
     | 
    
         
             
                    "ADD #{constraint_definition_sql(op)}"
         
     | 
| 
       246 
252 
     | 
    
         
             
                  when :drop_constraint
         
     | 
| 
       247 
     | 
    
         
            -
                    "DROP CONSTRAINT #{quoted_name}"
         
     | 
| 
      
 253 
     | 
    
         
            +
                    "DROP CONSTRAINT #{quoted_name}#{' CASCADE' if op[:cascade]}"
         
     | 
| 
       248 
254 
     | 
    
         
             
                  else
         
     | 
| 
       249 
255 
     | 
    
         
             
                    raise Error, "Unsupported ALTER TABLE operation"
         
     | 
| 
       250 
256 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -391,10 +397,15 @@ module Sequel 
     | 
|
| 
       391 
397 
     | 
    
         
             
                end
         
     | 
| 
       392 
398 
     | 
    
         | 
| 
       393 
399 
     | 
    
         
             
                # SQL DDL statement to drop the table with the given name.
         
     | 
| 
       394 
     | 
    
         
            -
                def drop_table_sql(name)
         
     | 
| 
       395 
     | 
    
         
            -
                  "DROP TABLE #{quote_schema_table(name)}"
         
     | 
| 
      
 400 
     | 
    
         
            +
                def drop_table_sql(name, options)
         
     | 
| 
      
 401 
     | 
    
         
            +
                  "DROP TABLE #{quote_schema_table(name)}#{' CASCADE' if options[:cascade]}"
         
     | 
| 
       396 
402 
     | 
    
         
             
                end
         
     | 
| 
       397 
403 
     | 
    
         | 
| 
      
 404 
     | 
    
         
            +
                # SQL DDL statement to drop a view with the given name.
         
     | 
| 
      
 405 
     | 
    
         
            +
                def drop_view_sql(name, options)
         
     | 
| 
      
 406 
     | 
    
         
            +
                  "DROP VIEW #{quote_schema_table(name)}#{' CASCADE' if options[:cascade]}"
         
     | 
| 
      
 407 
     | 
    
         
            +
                end
         
     | 
| 
      
 408 
     | 
    
         
            +
             
     | 
| 
       398 
409 
     | 
    
         
             
                # Proxy the filter_expr call to the dataset, used for creating constraints.
         
     | 
| 
       399 
410 
     | 
    
         
             
                def filter_expr(*args, &block)
         
     | 
| 
       400 
411 
     | 
    
         
             
                  schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr, *args, &block))
         
     | 
    
        data/lib/sequel/dataset.rb
    CHANGED
    
    | 
         @@ -26,6 +26,14 @@ module Sequel 
     | 
|
| 
       26 
26 
     | 
    
         
             
                extend Metaprogramming
         
     | 
| 
       27 
27 
     | 
    
         
             
                include Metaprogramming
         
     | 
| 
       28 
28 
     | 
    
         
             
                include Enumerable
         
     | 
| 
      
 29 
     | 
    
         
            +
                include SQL::AliasMethods
         
     | 
| 
      
 30 
     | 
    
         
            +
                include SQL::BooleanMethods
         
     | 
| 
      
 31 
     | 
    
         
            +
                include SQL::CastMethods
         
     | 
| 
      
 32 
     | 
    
         
            +
                include SQL::ComplexExpressionMethods
         
     | 
| 
      
 33 
     | 
    
         
            +
                include SQL::InequalityMethods
         
     | 
| 
      
 34 
     | 
    
         
            +
                include SQL::NumericMethods
         
     | 
| 
      
 35 
     | 
    
         
            +
                include SQL::OrderMethods
         
     | 
| 
      
 36 
     | 
    
         
            +
                include SQL::StringMethods
         
     | 
| 
       29 
37 
     | 
    
         
             
              end
         
     | 
| 
       30 
38 
     | 
    
         | 
| 
       31 
39 
     | 
    
         
             
              require(%w"query actions features graph prepared_statements misc mutation sql", 'dataset')
         
     | 
    
        data/lib/sequel/dataset/misc.rb
    CHANGED
    
    | 
         @@ -45,15 +45,6 @@ module Sequel 
     | 
|
| 
       45 
45 
     | 
    
         
             
                  self == o
         
     | 
| 
       46 
46 
     | 
    
         
             
                end
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                # Return the dataset as an aliased expression with the given alias. You can
         
     | 
| 
       49 
     | 
    
         
            -
                # use this as a FROM or JOIN dataset, or as a column if this dataset
         
     | 
| 
       50 
     | 
    
         
            -
                # returns a single row and column.
         
     | 
| 
       51 
     | 
    
         
            -
                #
         
     | 
| 
       52 
     | 
    
         
            -
                #   DB.from(DB[:table].as(:b)) # SELECT * FROM (SELECT * FROM table) AS b
         
     | 
| 
       53 
     | 
    
         
            -
                def as(aliaz)
         
     | 
| 
       54 
     | 
    
         
            -
                  ::Sequel::SQL::AliasedExpression.new(self, aliaz)
         
     | 
| 
       55 
     | 
    
         
            -
                end
         
     | 
| 
       56 
     | 
    
         
            -
                
         
     | 
| 
       57 
48 
     | 
    
         
             
                # Yield a dataset for each server in the connection pool that is tied to that server.
         
     | 
| 
       58 
49 
     | 
    
         
             
                # Intended for use in sharded environments where all servers need to be modified
         
     | 
| 
       59 
50 
     | 
    
         
             
                # with the same data:
         
     | 
    
        data/lib/sequel/dataset/query.rb
    CHANGED
    
    | 
         @@ -28,10 +28,10 @@ module Sequel 
     | 
|
| 
       28 
28 
     | 
    
         
             
                JOIN_METHODS = (CONDITIONED_JOIN_TYPES + UNCONDITIONED_JOIN_TYPES).map{|x| "#{x}_join".to_sym} + [:join, :join_table]
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
                # Methods that return modified datasets
         
     | 
| 
       31 
     | 
    
         
            -
                QUERY_METHODS = %w'add_graph_aliases and distinct except exclude
         
     | 
| 
      
 31 
     | 
    
         
            +
                QUERY_METHODS = %w'add_graph_aliases and distinct except exclude exclude_having exclude_where
         
     | 
| 
       32 
32 
     | 
    
         
             
                filter for_update from from_self graph grep group group_and_count group_by having intersect invert
         
     | 
| 
       33 
33 
     | 
    
         
             
                limit lock_style naked or order order_append order_by order_more order_prepend paginate qualify query
         
     | 
| 
       34 
     | 
    
         
            -
                reverse reverse_order select select_all select_append select_more server
         
     | 
| 
      
 34 
     | 
    
         
            +
                reverse reverse_order select select_all select_append select_group select_more server
         
     | 
| 
       35 
35 
     | 
    
         
             
                set_defaults set_graph_aliases set_overrides unfiltered ungraphed ungrouped union
         
     | 
| 
       36 
36 
     | 
    
         
             
                unlimited unordered where with with_recursive with_sql'.collect{|x| x.to_sym} + JOIN_METHODS
         
     | 
| 
       37 
37 
     | 
    
         | 
| 
         @@ -103,12 +103,29 @@ module Sequel 
     | 
|
| 
       103 
103 
     | 
    
         
             
                #   DB[:items].exclude(:category => 'software', :id=>3)
         
     | 
| 
       104 
104 
     | 
    
         
             
                #   # SELECT * FROM items WHERE ((category != 'software') OR (id != 3))
         
     | 
| 
       105 
105 
     | 
    
         
             
                def exclude(*cond, &block)
         
     | 
| 
       106 
     | 
    
         
            -
                   
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
      
 106 
     | 
    
         
            +
                  _filter_or_exclude(true, @opts[:having] ? :having : :where, *cond, &block)
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                # Inverts the given conditions and adds them to the HAVING clause.
         
     | 
| 
      
 110 
     | 
    
         
            +
                #
         
     | 
| 
      
 111 
     | 
    
         
            +
                #   DB[:items].select_group(:name).exclude_having{count(name) < 2}
         
     | 
| 
      
 112 
     | 
    
         
            +
                #   # SELECT name FROM items GROUP BY name HAVING (count(name) >= 2)
         
     | 
| 
      
 113 
     | 
    
         
            +
                def exclude_having(*cond, &block)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  _filter_or_exclude(true, :having, *cond, &block)
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                # Inverts the given conditions and adds them to the WHERE clause.
         
     | 
| 
      
 118 
     | 
    
         
            +
                #
         
     | 
| 
      
 119 
     | 
    
         
            +
                #   DB[:items].select_group(:name).exclude_where(:category => 'software')
         
     | 
| 
      
 120 
     | 
    
         
            +
                #   # SELECT * FROM items WHERE (category != 'software')
         
     | 
| 
      
 121 
     | 
    
         
            +
                #
         
     | 
| 
      
 122 
     | 
    
         
            +
                #   DB[:items].select_group(:name).
         
     | 
| 
      
 123 
     | 
    
         
            +
                #     exclude_having{count(name) < 2}.
         
     | 
| 
      
 124 
     | 
    
         
            +
                #     exclude_where(:category => 'software')
         
     | 
| 
      
 125 
     | 
    
         
            +
                #   # SELECT name FROM items WHERE (category != 'software')
         
     | 
| 
      
 126 
     | 
    
         
            +
                #   # GROUP BY name HAVING (count(name) >= 2)
         
     | 
| 
      
 127 
     | 
    
         
            +
                def exclude_where(*cond, &block)
         
     | 
| 
      
 128 
     | 
    
         
            +
                  _filter_or_exclude(true, :where, *cond, &block)
         
     | 
| 
       112 
129 
     | 
    
         
             
                end
         
     | 
| 
       113 
130 
     | 
    
         | 
| 
       114 
131 
     | 
    
         
             
                # Returns a copy of the dataset with the given conditions imposed upon it.  
         
     | 
| 
         @@ -270,21 +287,25 @@ module Sequel 
     | 
|
| 
       270 
287 
     | 
    
         
             
                end
         
     | 
| 
       271 
288 
     | 
    
         | 
| 
       272 
289 
     | 
    
         
             
                # Returns a copy of the dataset with the results grouped by the value of 
         
     | 
| 
       273 
     | 
    
         
            -
                # the given columns.
         
     | 
| 
      
 290 
     | 
    
         
            +
                # the given columns.  If a block is given, it is treated
         
     | 
| 
      
 291 
     | 
    
         
            +
                # as a virtual row block, similar to +filter+.
         
     | 
| 
       274 
292 
     | 
    
         
             
                #
         
     | 
| 
       275 
293 
     | 
    
         
             
                #   DB[:items].group(:id) # SELECT * FROM items GROUP BY id
         
     | 
| 
       276 
294 
     | 
    
         
             
                #   DB[:items].group(:id, :name) # SELECT * FROM items GROUP BY id, name
         
     | 
| 
       277 
     | 
    
         
            -
                 
     | 
| 
      
 295 
     | 
    
         
            +
                #   DB[:items].group{[a, sum(b)]} # SELECT * FROM items GROUP BY a, sum(b)
         
     | 
| 
      
 296 
     | 
    
         
            +
                def group(*columns, &block)
         
     | 
| 
      
 297 
     | 
    
         
            +
                  virtual_row_columns(columns, block)
         
     | 
| 
       278 
298 
     | 
    
         
             
                  clone(:group => (columns.compact.empty? ? nil : columns))
         
     | 
| 
       279 
299 
     | 
    
         
             
                end
         
     | 
| 
       280 
300 
     | 
    
         | 
| 
       281 
301 
     | 
    
         
             
                # Alias of group
         
     | 
| 
       282 
     | 
    
         
            -
                def group_by(*columns)
         
     | 
| 
       283 
     | 
    
         
            -
                  group(*columns)
         
     | 
| 
      
 302 
     | 
    
         
            +
                def group_by(*columns, &block)
         
     | 
| 
      
 303 
     | 
    
         
            +
                  group(*columns, &block)
         
     | 
| 
       284 
304 
     | 
    
         
             
                end
         
     | 
| 
       285 
305 
     | 
    
         | 
| 
       286 
306 
     | 
    
         
             
                # Returns a dataset grouped by the given column with count by group.
         
     | 
| 
       287 
307 
     | 
    
         
             
                # Column aliases may be supplied, and will be included in the select clause.
         
     | 
| 
      
 308 
     | 
    
         
            +
                # If a block is given, it is treated as a virtual row block, similar to +filter+.
         
     | 
| 
       288 
309 
     | 
    
         
             
                #
         
     | 
| 
       289 
310 
     | 
    
         
             
                # Examples:
         
     | 
| 
       290 
311 
     | 
    
         
             
                #
         
     | 
| 
         @@ -299,8 +320,12 @@ module Sequel 
     | 
|
| 
       299 
320 
     | 
    
         
             
                #   DB[:items].group_and_count(:first_name___name).all
         
     | 
| 
       300 
321 
     | 
    
         
             
                #   # SELECT first_name AS name, count(*) AS count FROM items GROUP BY first_name
         
     | 
| 
       301 
322 
     | 
    
         
             
                #   # => [{:name=>'a', :count=>1}, ...]
         
     | 
| 
       302 
     | 
    
         
            -
                 
     | 
| 
       303 
     | 
    
         
            -
             
     | 
| 
      
 323 
     | 
    
         
            +
                #
         
     | 
| 
      
 324 
     | 
    
         
            +
                #   DB[:items].group_and_count{substr(first_name, 1, 1).as(initial)}.all
         
     | 
| 
      
 325 
     | 
    
         
            +
                #   # SELECT substr(first_name, 1, 1) AS initial, count(*) AS count FROM items GROUP BY substr(first_name, 1, 1)
         
     | 
| 
      
 326 
     | 
    
         
            +
                #   # => [{:initial=>'a', :count=>1}, ...]
         
     | 
| 
      
 327 
     | 
    
         
            +
                def group_and_count(*columns, &block)
         
     | 
| 
      
 328 
     | 
    
         
            +
                  select_group(*columns, &block).select_more(COUNT_OF_ALL_AS_COUNT)
         
     | 
| 
       304 
329 
     | 
    
         
             
                end
         
     | 
| 
       305 
330 
     | 
    
         | 
| 
       306 
331 
     | 
    
         
             
                # Returns a copy of the dataset with the HAVING conditions changed. See #filter for argument types.
         
     | 
| 
         @@ -532,7 +557,7 @@ module Sequel 
     | 
|
| 
       532 
557 
     | 
    
         
             
                #   DB[:items].order{sum(name).desc} # SELECT * FROM items ORDER BY sum(name) DESC
         
     | 
| 
       533 
558 
     | 
    
         
             
                #   DB[:items].order(nil) # SELECT * FROM items
         
     | 
| 
       534 
559 
     | 
    
         
             
                def order(*columns, &block)
         
     | 
| 
       535 
     | 
    
         
            -
                  columns  
     | 
| 
      
 560 
     | 
    
         
            +
                  virtual_row_columns(columns, block)
         
     | 
| 
       536 
561 
     | 
    
         
             
                  clone(:order => (columns.compact.empty?) ? nil : columns)
         
     | 
| 
       537 
562 
     | 
    
         
             
                end
         
     | 
| 
       538 
563 
     | 
    
         | 
| 
         @@ -630,7 +655,7 @@ module Sequel 
     | 
|
| 
       630 
655 
     | 
    
         
             
                #   DB[:items].select(:a, :b) # SELECT a, b FROM items
         
     | 
| 
       631 
656 
     | 
    
         
             
                #   DB[:items].select{[a, sum(b)]} # SELECT a, sum(b) FROM items
         
     | 
| 
       632 
657 
     | 
    
         
             
                def select(*columns, &block)
         
     | 
| 
       633 
     | 
    
         
            -
                  columns  
     | 
| 
      
 658 
     | 
    
         
            +
                  virtual_row_columns(columns, block)
         
     | 
| 
       634 
659 
     | 
    
         
             
                  m = []
         
     | 
| 
       635 
660 
     | 
    
         
             
                  columns.each do |i|
         
     | 
| 
       636 
661 
     | 
    
         
             
                    i.is_a?(Hash) ? m.concat(i.map{|k, v| SQL::AliasedExpression.new(k,v)}) : m << i
         
     | 
| 
         @@ -638,11 +663,19 @@ module Sequel 
     | 
|
| 
       638 
663 
     | 
    
         
             
                  clone(:select => m)
         
     | 
| 
       639 
664 
     | 
    
         
             
                end
         
     | 
| 
       640 
665 
     | 
    
         | 
| 
       641 
     | 
    
         
            -
                # Returns a copy of the dataset selecting the wildcard 
     | 
| 
      
 666 
     | 
    
         
            +
                # Returns a copy of the dataset selecting the wildcard if no arguments
         
     | 
| 
      
 667 
     | 
    
         
            +
                # are given.  If arguments are given, treat them as tables and select
         
     | 
| 
      
 668 
     | 
    
         
            +
                # all columns (using the wildcard) from each table.
         
     | 
| 
       642 
669 
     | 
    
         
             
                #
         
     | 
| 
       643 
670 
     | 
    
         
             
                #   DB[:items].select(:a).select_all # SELECT * FROM items
         
     | 
| 
       644 
     | 
    
         
            -
                 
     | 
| 
       645 
     | 
    
         
            -
             
     | 
| 
      
 671 
     | 
    
         
            +
                #   DB[:items].select_all(:items) # SELECT items.* FROM items
         
     | 
| 
      
 672 
     | 
    
         
            +
                #   DB[:items].select_all(:items, :foo) # SELECT items.*, foo.* FROM items
         
     | 
| 
      
 673 
     | 
    
         
            +
                def select_all(*tables)
         
     | 
| 
      
 674 
     | 
    
         
            +
                  if tables.empty?
         
     | 
| 
      
 675 
     | 
    
         
            +
                    clone(:select => nil)
         
     | 
| 
      
 676 
     | 
    
         
            +
                  else
         
     | 
| 
      
 677 
     | 
    
         
            +
                    select(*tables.map{|t| SQL::ColumnAll.new(t)})
         
     | 
| 
      
 678 
     | 
    
         
            +
                  end
         
     | 
| 
       646 
679 
     | 
    
         
             
                end
         
     | 
| 
       647 
680 
     | 
    
         | 
| 
       648 
681 
     | 
    
         
             
                # Returns a copy of the dataset with the given columns added
         
     | 
| 
         @@ -658,6 +691,20 @@ module Sequel 
     | 
|
| 
       658 
691 
     | 
    
         
             
                  select(*(cur_sel + columns), &block)
         
     | 
| 
       659 
692 
     | 
    
         
             
                end
         
     | 
| 
       660 
693 
     | 
    
         | 
| 
      
 694 
     | 
    
         
            +
                # Set both the select and group clauses with the given +columns+.
         
     | 
| 
      
 695 
     | 
    
         
            +
                # Column aliases may be supplied, and will be included in the select clause.
         
     | 
| 
      
 696 
     | 
    
         
            +
                # This also takes a virtual row block similar to +filter+.
         
     | 
| 
      
 697 
     | 
    
         
            +
                #
         
     | 
| 
      
 698 
     | 
    
         
            +
                #   DB[:items].select_group(:a, :b)
         
     | 
| 
      
 699 
     | 
    
         
            +
                #   # SELECT a, b FROM items GROUP BY a, b
         
     | 
| 
      
 700 
     | 
    
         
            +
                #
         
     | 
| 
      
 701 
     | 
    
         
            +
                #   DB[:items].select_group(:c___a){f(c2)}
         
     | 
| 
      
 702 
     | 
    
         
            +
                #   # SELECT c AS a, f(c2) FROM items GROUP BY c, f(c2)
         
     | 
| 
      
 703 
     | 
    
         
            +
                def select_group(*columns, &block)
         
     | 
| 
      
 704 
     | 
    
         
            +
                  virtual_row_columns(columns, block)
         
     | 
| 
      
 705 
     | 
    
         
            +
                  select(*columns).group(*columns.map{|c| unaliased_identifier(c)})
         
     | 
| 
      
 706 
     | 
    
         
            +
                end
         
     | 
| 
      
 707 
     | 
    
         
            +
             
     | 
| 
       661 
708 
     | 
    
         
             
                # Returns a copy of the dataset with the given columns added
         
     | 
| 
       662 
709 
     | 
    
         
             
                # to the existing selected columns. If no columns are currently selected
         
     | 
| 
       663 
710 
     | 
    
         
             
                # it will just select the columns given. 
         
     | 
| 
         @@ -840,17 +887,29 @@ module Sequel 
     | 
|
| 
       840 
887 
     | 
    
         | 
| 
       841 
888 
     | 
    
         
             
                private
         
     | 
| 
       842 
889 
     | 
    
         | 
| 
       843 
     | 
    
         
            -
                # Internal filter method so it works on either the having or where clauses.
         
     | 
| 
       844 
     | 
    
         
            -
                def  
     | 
| 
      
 890 
     | 
    
         
            +
                # Internal filter/exclude method so it works on either the having or where clauses.
         
     | 
| 
      
 891 
     | 
    
         
            +
                def _filter_or_exclude(invert, clause, *cond, &block)
         
     | 
| 
       845 
892 
     | 
    
         
             
                  cond = cond.first if cond.size == 1
         
     | 
| 
       846 
893 
     | 
    
         
             
                  if cond.respond_to?(:empty?) && cond.empty? && !block
         
     | 
| 
       847 
894 
     | 
    
         
             
                    clone
         
     | 
| 
       848 
895 
     | 
    
         
             
                  else
         
     | 
| 
       849 
896 
     | 
    
         
             
                    cond = filter_expr(cond, &block)
         
     | 
| 
      
 897 
     | 
    
         
            +
                    cond = SQL::BooleanExpression.invert(cond) if invert
         
     | 
| 
       850 
898 
     | 
    
         
             
                    cond = SQL::BooleanExpression.new(:AND, @opts[clause], cond) if @opts[clause]
         
     | 
| 
       851 
899 
     | 
    
         
             
                    clone(clause => cond)
         
     | 
| 
       852 
900 
     | 
    
         
             
                  end
         
     | 
| 
       853 
901 
     | 
    
         
             
                end
         
     | 
| 
      
 902 
     | 
    
         
            +
             
     | 
| 
      
 903 
     | 
    
         
            +
                # Internal filter method so it works on either the having or where clauses.
         
     | 
| 
      
 904 
     | 
    
         
            +
                def _filter(clause, *cond, &block)
         
     | 
| 
      
 905 
     | 
    
         
            +
                  _filter_or_exclude(false, clause, *cond, &block)
         
     | 
| 
      
 906 
     | 
    
         
            +
                end
         
     | 
| 
      
 907 
     | 
    
         
            +
             
     | 
| 
      
 908 
     | 
    
         
            +
                # Treat the +block+ as a virtual_row block if not +nil+ and
         
     | 
| 
      
 909 
     | 
    
         
            +
                # add the resulting columns to the +columns+ array (modifies +columns+).
         
     | 
| 
      
 910 
     | 
    
         
            +
                def virtual_row_columns(columns, block)
         
     | 
| 
      
 911 
     | 
    
         
            +
                  columns.concat(Array(Sequel.virtual_row(&block))) if block
         
     | 
| 
      
 912 
     | 
    
         
            +
                end
         
     | 
| 
       854 
913 
     | 
    
         | 
| 
       855 
914 
     | 
    
         
             
                # Add the dataset to the list of compounds
         
     | 
| 
       856 
915 
     | 
    
         
             
                def compound_clone(type, dataset, opts)
         
     |