sequel 3.13.0 → 3.14.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.
Files changed (60) hide show
  1. data/CHANGELOG +36 -0
  2. data/doc/release_notes/3.14.0.txt +118 -0
  3. data/lib/sequel/adapters/oracle.rb +7 -2
  4. data/lib/sequel/adapters/shared/mssql.rb +9 -3
  5. data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
  6. data/lib/sequel/connection_pool/threaded.rb +3 -3
  7. data/lib/sequel/database/connecting.rb +47 -11
  8. data/lib/sequel/database/dataset.rb +17 -6
  9. data/lib/sequel/database/dataset_defaults.rb +15 -3
  10. data/lib/sequel/database/logging.rb +4 -3
  11. data/lib/sequel/database/misc.rb +33 -21
  12. data/lib/sequel/database/query.rb +61 -22
  13. data/lib/sequel/database/schema_generator.rb +108 -45
  14. data/lib/sequel/database/schema_methods.rb +8 -5
  15. data/lib/sequel/dataset/actions.rb +194 -45
  16. data/lib/sequel/dataset/features.rb +1 -1
  17. data/lib/sequel/dataset/graph.rb +51 -43
  18. data/lib/sequel/dataset/misc.rb +29 -5
  19. data/lib/sequel/dataset/mutation.rb +0 -1
  20. data/lib/sequel/dataset/prepared_statements.rb +14 -2
  21. data/lib/sequel/dataset/query.rb +268 -125
  22. data/lib/sequel/dataset/sql.rb +33 -44
  23. data/lib/sequel/extensions/migration.rb +3 -2
  24. data/lib/sequel/extensions/pagination.rb +1 -1
  25. data/lib/sequel/model/associations.rb +89 -87
  26. data/lib/sequel/model/base.rb +386 -109
  27. data/lib/sequel/model/errors.rb +15 -1
  28. data/lib/sequel/model/exceptions.rb +3 -3
  29. data/lib/sequel/model/inflections.rb +2 -2
  30. data/lib/sequel/model/plugins.rb +9 -5
  31. data/lib/sequel/plugins/rcte_tree.rb +43 -15
  32. data/lib/sequel/plugins/schema.rb +6 -5
  33. data/lib/sequel/plugins/serialization.rb +1 -1
  34. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  35. data/lib/sequel/plugins/tree.rb +33 -1
  36. data/lib/sequel/timezones.rb +16 -10
  37. data/lib/sequel/version.rb +1 -1
  38. data/spec/adapters/mssql_spec.rb +36 -2
  39. data/spec/adapters/mysql_spec.rb +4 -4
  40. data/spec/adapters/postgres_spec.rb +1 -1
  41. data/spec/adapters/spec_helper.rb +2 -2
  42. data/spec/core/database_spec.rb +8 -1
  43. data/spec/core/dataset_spec.rb +36 -1
  44. data/spec/extensions/pagination_spec.rb +1 -1
  45. data/spec/extensions/rcte_tree_spec.rb +40 -8
  46. data/spec/extensions/schema_spec.rb +5 -0
  47. data/spec/extensions/serialization_spec.rb +4 -4
  48. data/spec/extensions/single_table_inheritance_spec.rb +7 -0
  49. data/spec/extensions/tree_spec.rb +36 -0
  50. data/spec/integration/dataset_test.rb +19 -0
  51. data/spec/integration/prepared_statement_test.rb +2 -2
  52. data/spec/integration/schema_test.rb +1 -1
  53. data/spec/integration/spec_helper.rb +4 -4
  54. data/spec/integration/timezone_test.rb +27 -21
  55. data/spec/model/associations_spec.rb +5 -5
  56. data/spec/model/dataset_methods_spec.rb +13 -0
  57. data/spec/model/hooks_spec.rb +31 -0
  58. data/spec/model/record_spec.rb +24 -7
  59. data/spec/model/validations_spec.rb +9 -4
  60. metadata +6 -4
data/CHANGELOG CHANGED
@@ -1,3 +1,39 @@
1
+ === 3.14.0 (2010-08-02)
2
+
3
+ * Handle OCIInvalidHandle errors when disconnecting in the Oracle adapter (jeremyevans)
4
+
5
+ * Allow calling Model.create_table, .create_table! and .create_table? with blocks containing the schema in the schema plugin (jfirebaugh)
6
+
7
+ * Fix handling of a :conditions options in the rcte plugin (mluu)
8
+
9
+ * Fix aggregate methods such as Dataset#sum and #avg on MSSQL on datasets with an order but no limit (mluu)
10
+
11
+ * Fix rename_table on MSSQL for case sensitive collations and schemas (mluu)
12
+
13
+ * Add a :single_root option to the tree plugin, for enforcing a single root value via a before_save hook (jfirebaugh)
14
+
15
+ * Add a Model#root? method to the tree plugin, for checking if the current node is a root (jfirebaugh)
16
+
17
+ * Add a :raise_on_failure option to Model#save to override the raise_on_save_failure setting (jfirebaugh)
18
+
19
+ * Handle class discriminator column names that are existing ruby method names in the single table inheritance plugin (jeremyevans)
20
+
21
+ * Fix times and datetimes when timezone support is used and you are loading a standard time when in daylight time or vice versa (gcampbell)
22
+
23
+ * Handle literalization of OCI8::CLOB objects in the native oracle adapter (jeremyevans)
24
+
25
+ * Raise a Sequel::Error instead of an ArgumentError if the migration current or target version does not exist (jeremyevans)
26
+
27
+ * Fix Database#schema on Oracle when the same table exists in multiple schemas (djwhitt)
28
+
29
+ * Fix Database#each_server when using a connection string to connect (jeremyevans)
30
+
31
+ * Make Model dataset's destroy method respect the model's use_transactions setting, instead of always using a transaction (jeremyevans)
32
+
33
+ * Add Database#adapter_scheme, for checking which adapter a Database uses (jeremyevans)
34
+
35
+ * Allow Dataset#grep to take :all_patterns, :all_columns, and :case_insensitive options (mighub, jeremyevans)
36
+
1
37
  === 3.13.0 (2010-07-01)
2
38
 
3
39
  * Allow Model.find_or_create to take a block which is yielded the object to be created, if no object is found (zaius, jeremyevans)
@@ -0,0 +1,118 @@
1
+ = New Features
2
+
3
+ * Dataset#grep now accepts :all_patterns, :all_columns, and
4
+ :case_insensitive options. Previously, grep would use a case
5
+ sensitive search where it would match if any pattern matched any
6
+ column. These three options give you more control over how the
7
+ pattern matching will work:
8
+
9
+ dataset.grep([:a, :b], %w'%test% foo')
10
+ # WHERE ((a LIKE '%test%') OR (a LIKE 'foo')
11
+ # OR (b LIKE '%test%') OR (b LIKE 'foo'))
12
+
13
+ dataset.grep([:a, :b], %w'%foo% %bar%', :all_patterns=>true)
14
+ # WHERE (((a LIKE '%foo%') OR (b LIKE '%foo%'))
15
+ # AND ((a LIKE '%bar%') OR (b LIKE '%bar%')))
16
+
17
+ dataset.grep([:a, :b], %w'%foo% %bar%', :all_columns=>true)
18
+ # WHERE (((a LIKE '%foo%') OR (a LIKE '%bar%'))
19
+ # AND ((b LIKE '%foo%') OR (b LIKE '%bar%')))
20
+
21
+ dataset.grep([:a, :b], %w'%foo% %bar%',
22
+ :all_patterns=>true,:all_columns=>true)
23
+ # WHERE ((a LIKE '%foo%') AND (b LIKE '%foo%')
24
+ # AND (a LIKE '%bar%') AND (b LIKE '%bar%'))
25
+
26
+ dataset.grep([:a, :b], %w'%test% foo', :case_insensitive=>true)
27
+ # WHERE ((a ILIKE '%test%') OR (a ILIKE 'foo')
28
+ # OR (b ILIKE '%test%') OR (b ILIKE 'foo'))
29
+
30
+ * When using the schema plugin, you can now provide a block to the
31
+ create_table methods to set the schema and create the table
32
+ in the same call:
33
+
34
+ class Artist < Sequel::Model
35
+ create_table do
36
+ primary_key :id
37
+ String :name
38
+ end
39
+ end
40
+
41
+ * The tree plugin now accepts a :single_root option, which uses a
42
+ before_save hook to attempt to ensure that there is only a single
43
+ root in the tree. It also adds a Model.root method to get the
44
+ single root of the tree.
45
+
46
+ * The tree plugin now adds a Model#root? instance method to check
47
+ if the current node is a root of the tree.
48
+
49
+ * Model#save now takes a :raise_on_failure option which will
50
+ override the object's raise_on_save_failure setting. This makes
51
+ it easier to get the desired behavior (raise or just return false)
52
+ in library code without using a begin/ensure block.
53
+
54
+ * The Database#adapter_scheme instance method was added, which
55
+ operates the same as the class method.
56
+
57
+ * Sequel now handles the literalization of OCI8::CLOB objects in
58
+ the Oracle adapter.
59
+
60
+ = Other Improvements
61
+
62
+ * When using the timezone support, Sequel will now correctly load
63
+ times and datetimes in standard time when the current timezone is
64
+ in daylight time, or vice versa. Previously, if you tried to
65
+ to load a time or datetime in December when in July in a timezone
66
+ that used daylight time, it would be off by an hour.
67
+
68
+ * The rcte_tree plugin now works correctly when a :conditions option
69
+ is used.
70
+
71
+ * The single_table_inheritance plugin now works correctly when the
72
+ class discriminator column has the same name as an existing ruby
73
+ method (such as type).
74
+
75
+ * Database#each_server now works correctly when a connection string
76
+ is used to connect, instead of an options hash.
77
+
78
+ * Model#destroy now respects the object's use_transactions setting,
79
+ instead of always using a transaction.
80
+
81
+ * Model#exists? now uses a simpler and faster query.
82
+
83
+ * Sequel now handles the aggregate methods such as count and sum
84
+ correctly on Microsoft SQL Server when using an ordered dataset
85
+ with a clause such as DISTINCT or GROUP and without a limit.
86
+
87
+ * Sequel now handles rename_table correctly on Microsoft SQL Server
88
+ when using a case sensitive collation, or when qualifying the
89
+ table with a schema.
90
+
91
+ * Sequel now parses the schema correctly on Oracle when the same
92
+ table name is used in multiple schemas.
93
+
94
+ * Sequel now handles OCIInvalidHandle errors when disconnecting
95
+ in the Oracle adapter.
96
+
97
+ * Sequel now raises a Sequel::Error instead of an ArgumentError
98
+ if the current or target migration version does not exist.
99
+
100
+ * When a mismatched number of composite keys are used in
101
+ associations, Sequel now uses a more detailed error message.
102
+
103
+ * Significant improvements were made to the Dataset and Model
104
+ RDoc documentation.
105
+
106
+ = Backwards Compatibility
107
+
108
+ * Model#valid? now must accept an optional options hash.
109
+
110
+ * The Model#save_failure private method was renamed to
111
+ raise_hook_failure.
112
+
113
+ * The LOCAL_DATETIME_OFFSET_SECS and LOCAL_DATETIME_OFFSET constants
114
+ have been removed from the Sequel module.
115
+
116
+ * Sequel now uses obj.to_json instead of JSON.generate(obj). This
117
+ shouldn't affect backwards compatibility, but did fix a bug in
118
+ certain cases.
@@ -34,9 +34,9 @@ module Sequel
34
34
  def schema_parse_table(table, opts={})
35
35
  ds = dataset
36
36
  ds.identifier_output_method = :downcase
37
- schema, table = schema_and_table(table)
37
+ schema_and_table = "#{"#{quote_identifier(opts[:schema])}." if opts[:schema]}#{quote_identifier(table)}"
38
38
  table_schema = []
39
- metadata = transaction(opts){|conn| conn.describe_table(table.to_s)}
39
+ metadata = transaction(opts){|conn| conn.describe_table(schema_and_table)}
40
40
  metadata.columns.each do |column|
41
41
  table_schema << [
42
42
  column.name.downcase.to_sym,
@@ -85,6 +85,8 @@ module Sequel
85
85
 
86
86
  def disconnect_connection(c)
87
87
  c.logoff
88
+ rescue OCIInvalidHandle
89
+ nil
88
90
  end
89
91
 
90
92
  def remove_transaction(conn)
@@ -122,6 +124,9 @@ module Sequel
122
124
  case v
123
125
  when OraDate
124
126
  literal(Sequel.database_to_application_timestamp(v))
127
+ when OCI8::CLOB
128
+ v.rewind
129
+ literal(v.read)
125
130
  else
126
131
  super
127
132
  end
@@ -67,7 +67,7 @@ module Sequel
67
67
  when :add_column
68
68
  "ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op)}"
69
69
  when :rename_column
70
- "SP_RENAME #{literal("#{quote_schema_table(table)}.#{quote_identifier(op[:name])}")}, #{literal(op[:new_name].to_s)}, 'COLUMN'"
70
+ "sp_rename #{literal("#{quote_schema_table(table)}.#{quote_identifier(op[:name])}")}, #{literal(op[:new_name].to_s)}, 'COLUMN'"
71
71
  when :set_column_type
72
72
  "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} #{type_literal(op)}"
73
73
  when :set_column_null
@@ -124,9 +124,9 @@ module Sequel
124
124
  ds
125
125
  end
126
126
 
127
- # Use SP_RENAME to rename the table
127
+ # Use sp_rename to rename the table
128
128
  def rename_table_sql(name, new_name)
129
- "SP_RENAME #{quote_schema_table(name)}, #{quote_schema_table(new_name)}"
129
+ "sp_rename #{literal(quote_schema_table(name))}, #{quote_identifier(schema_and_table(new_name).pop)}"
130
130
  end
131
131
 
132
132
  # SQL to rollback to a savepoint
@@ -373,6 +373,12 @@ module Sequel
373
373
  def supports_window_functions?
374
374
  true
375
375
  end
376
+
377
+ protected
378
+ # MSSQL does not allow ordering in sub-clauses unless 'top' (limit) is specified
379
+ def aggregate_dataset
380
+ (options_overlap(Sequel::Dataset::COUNT_FROM_SELF_OPTS) && !options_overlap([:limit])) ? unordered.from_self : super
381
+ end
376
382
 
377
383
  private
378
384
 
@@ -56,7 +56,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
56
56
  @allocated[server].length + @available_connections[server].length
57
57
  end
58
58
 
59
- # Removes all connection currently available on all servers, optionally
59
+ # Removes all connections currently available on all servers, optionally
60
60
  # yielding each connection to the given block. This method has the effect of
61
61
  # disconnecting from the database, assuming that no connections are currently
62
62
  # being used. If connections are being used, they are scheduled to be
@@ -1,4 +1,5 @@
1
1
  # A connection pool allowing multi-threaded access to a pool of connections.
2
+ # This is the default connection pool used by Sequel.
2
3
  class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
3
4
  # The maximum number of connections this pool will create (per shard/server
4
5
  # if sharding).
@@ -35,11 +36,10 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
35
36
  @allocated.length + @available_connections.length
36
37
  end
37
38
 
38
- # Removes all connection currently available on all servers, optionally
39
+ # Removes all connections currently available on all servers, optionally
39
40
  # yielding each connection to the given block. This method has the effect of
40
41
  # disconnecting from the database, assuming that no connections are currently
41
- # being used. If connections are being used, they are scheduled to be
42
- # disconnected as soon as they are returned to the pool.
42
+ # being used.
43
43
  #
44
44
  # Once a connection is requested using #hold, the connection pool
45
45
  # creates new connections to the database.
@@ -27,13 +27,13 @@ module Sequel
27
27
 
28
28
  # make sure we actually loaded the adapter
29
29
  unless klass = ADAPTER_MAP[scheme]
30
- raise AdapterNotFound, "Could not load #{scheme} adapter"
30
+ raise AdapterNotFound, "Could not load #{scheme} adapter: adapter class not registered in ADAPTER_MAP"
31
31
  end
32
32
  end
33
33
  klass
34
34
  end
35
35
 
36
- # Returns the scheme for the Database class.
36
+ # Returns the scheme symbol for the Database class.
37
37
  def self.adapter_scheme
38
38
  @scheme
39
39
  end
@@ -54,6 +54,7 @@ module Sequel
54
54
  uri.query.split('&').collect{|s| s.split('=')}.each{|k,v| uri_options[k.to_sym] = v if k && !k.empty?} unless uri.query.to_s.strip.empty?
55
55
  uri_options.entries.each{|k,v| uri_options[k] = URI.unescape(v) if v.is_a?(String)}
56
56
  opts = uri_options.merge(opts)
57
+ opts[:adapter] = scheme
57
58
  end
58
59
  when Hash
59
60
  opts = conn_string.merge(opts)
@@ -62,7 +63,7 @@ module Sequel
62
63
  raise Error, "Sequel::Database.connect takes either a Hash or a String, given: #{conn_string.inspect}"
63
64
  end
64
65
  # process opts a bit
65
- opts = opts.inject({}) do |m, kv| k, v = *kv
66
+ opts = opts.inject({}) do |m, (k,v)|
66
67
  k = :user if k.to_s == 'username'
67
68
  m[k.to_sym] = v
68
69
  m
@@ -104,9 +105,20 @@ module Sequel
104
105
  end
105
106
  private_class_method :set_adapter_scheme
106
107
 
107
- # The connection pool for this database
108
+ # The connection pool for this Database instance. All Database instances have
109
+ # their own connection pools.
108
110
  attr_reader :pool
109
111
 
112
+ # Returns the scheme symbol for this instance's class, which reflects which
113
+ # adapter is being used. In some cases, this can be the same as the
114
+ # +database_type+ (for native adapters), in others (i.e. adapters with
115
+ # subadapters), it will be different.
116
+ #
117
+ # Sequel.connect('jdbc:postgres://...').adapter_scheme # => :jdbc
118
+ def adapter_scheme
119
+ self.class.adapter_scheme
120
+ end
121
+
110
122
  # Dynamically add new servers or modify server options at runtime. Also adds new
111
123
  # servers to the connection pool. Intended for use with master/slave or shard
112
124
  # configurations where it is useful to add new server hosts at runtime.
@@ -115,7 +127,7 @@ module Sequel
115
127
  # proc values. If a servers key is already in use, it's value is overridden
116
128
  # with the value provided.
117
129
  #
118
- # DB.add_servers(:f=>{:host=>"hash_host_f"})
130
+ # DB.add_servers(:f=>{:host=>"hash_host_f"})
119
131
  def add_servers(servers)
120
132
  @opts[:servers] = @opts[:servers] ? @opts[:servers].merge(servers) : servers
121
133
  @pool.add_servers(servers.keys)
@@ -133,19 +145,27 @@ module Sequel
133
145
  # type. Even better, you can tell that two Database objects that are using
134
146
  # the same adapter are connecting to different database types (think JDBC or
135
147
  # DataObjects).
148
+ #
149
+ # Sequel.connect('jdbc:postgres://...').database_type # => :postgres
136
150
  def database_type
137
- self.class.adapter_scheme
151
+ adapter_scheme
138
152
  end
139
153
 
140
154
  # Disconnects all available connections from the connection pool. Any
141
155
  # connections currently in use will not be disconnected. Options:
142
156
  # * :servers - Should be a symbol specifing the server to disconnect from,
143
157
  # or an array of symbols to specify multiple servers.
158
+ #
159
+ # Example:
160
+ #
161
+ # DB.disconnect # All servers
162
+ # DB.disconnect(:servers=>:server1) # Single server
163
+ # DB.disconnect(:servers=>[:server1, :server2]) # Multiple servers
144
164
  def disconnect(opts = {})
145
165
  pool.disconnect(opts)
146
166
  end
147
167
 
148
- # Yield a new database object for every server in the connection pool.
168
+ # Yield a new Database instance for every server in the connection pool.
149
169
  # Intended for use in sharded environments where there is a need to make schema
150
170
  # modifications (DDL queries) on each shard.
151
171
  #
@@ -175,6 +195,9 @@ module Sequel
175
195
  end
176
196
 
177
197
  # An array of servers/shards for this Database object.
198
+ #
199
+ # DB.servers # Unsharded: => [:default]
200
+ # DB.servers # Sharded: => [:default, :server1, :server2]
178
201
  def servers
179
202
  pool.servers
180
203
  end
@@ -184,13 +207,27 @@ module Sequel
184
207
  @single_threaded
185
208
  end
186
209
 
187
- # Acquires a database connection, yielding it to the passed block.
210
+ # Acquires a database connection, yielding it to the passed block. This is
211
+ # useful if you want to make sure the same connection is used for all
212
+ # database queries in the block. It is also useful if you want to gain
213
+ # direct access to the underlying connection object if you need to do
214
+ # something Sequel does not natively support.
215
+ #
216
+ # If a server option is given, acquires a connection for that specific
217
+ # server, instead of the :default server.
218
+ #
219
+ #
220
+ # DB.synchronize do |conn|
221
+ # ...
222
+ # end
188
223
  def synchronize(server=nil, &block)
189
224
  @pool.hold(server || :default, &block)
190
225
  end
191
226
 
192
227
  # Attempts to acquire a database connection. Returns true if successful.
193
- # Will probably raise an error if unsuccessful.
228
+ # Will probably raise an Error if unsuccessful. If a server argument
229
+ # is given, attempts to acquire a database connection to the given
230
+ # server/shard.
194
231
  def test_connection(server=nil)
195
232
  synchronize(server){|conn|}
196
233
  true
@@ -207,7 +244,7 @@ module Sequel
207
244
  # options for all server with the specific options for the given
208
245
  # server specified in the :servers option.
209
246
  def server_opts(server)
210
- opts = if @opts[:servers] && server_options = @opts[:servers][server]
247
+ opts = if @opts[:servers] and server_options = @opts[:servers][server]
211
248
  case server_options
212
249
  when Hash
213
250
  @opts.merge(server_options)
@@ -222,6 +259,5 @@ module Sequel
222
259
  opts.delete(:servers)
223
260
  opts
224
261
  end
225
-
226
262
  end
227
263
  end
@@ -5,10 +5,11 @@ module Sequel
5
5
  # These methods all return instances of this database's dataset class.
6
6
  # ---------------------
7
7
 
8
- # Returns a dataset from the database. If the first argument is a string,
8
+ # Returns a dataset for the database. If the first argument is a string,
9
9
  # the method acts as an alias for Database#fetch, returning a dataset for
10
- # arbitrary SQL:
10
+ # arbitrary SQL, with or without placeholders:
11
11
  #
12
+ # DB['SELECT * FROM items'].all
12
13
  # DB['SELECT * FROM items WHERE name = ?', my_name].all
13
14
  #
14
15
  # Otherwise, acts as an alias for Database#from, setting the primary
@@ -19,7 +20,10 @@ module Sequel
19
20
  (String === args.first) ? fetch(*args) : from(*args)
20
21
  end
21
22
 
22
- # Returns a blank dataset for this database
23
+ # Returns a blank dataset for this database.
24
+ #
25
+ # DB.dataset # SELECT *
26
+ # DB.dataset.from(:items) # SELECT * FROM items
23
27
  def dataset
24
28
  ds = Sequel::Dataset.new(self)
25
29
  end
@@ -29,11 +33,11 @@ module Sequel
29
33
  #
30
34
  # DB.fetch('SELECT * FROM items'){|r| p r}
31
35
  #
32
- # The method returns a dataset instance:
36
+ # The +fetch+ method returns a dataset instance:
33
37
  #
34
38
  # DB.fetch('SELECT * FROM items').all
35
39
  #
36
- # Fetch can also perform parameterized queries for protection against SQL
40
+ # +fetch+ can also perform parameterized queries for protection against SQL
37
41
  # injection:
38
42
  #
39
43
  # DB.fetch('SELECT * FROM items WHERE name = ?', my_name).all
@@ -43,14 +47,21 @@ module Sequel
43
47
  ds
44
48
  end
45
49
 
46
- # Returns a new dataset with the from method invoked. If a block is given,
50
+ # Returns a new dataset with the +from+ method invoked. If a block is given,
47
51
  # it is used as a filter on the dataset.
52
+ #
53
+ # DB.from(:items) # SELECT * FROM items
54
+ # DB.from(:items){id > 2} # SELECT * FROM items WHERE (id > 2)
48
55
  def from(*args, &block)
49
56
  ds = dataset.from(*args)
50
57
  block ? ds.filter(&block) : ds
51
58
  end
52
59
 
53
60
  # Returns a new dataset with the select method invoked.
61
+ #
62
+ # DB.select(1) # SELECT 1
63
+ # DB.select{server_version{}} # SELECT server_version()
64
+ # DB.select(:id).from(:items) # SELECT id FROM items
54
65
  def select(*args, &block)
55
66
  dataset.select(*args, &block)
56
67
  end