sequel 3.10.0 → 3.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +68 -0
- data/COPYING +1 -1
- data/README.rdoc +87 -27
- data/bin/sequel +2 -4
- data/doc/association_basics.rdoc +1383 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/opening_databases.rdoc +45 -16
- data/doc/querying.rdoc +210 -0
- data/doc/release_notes/3.11.0.txt +254 -0
- data/doc/virtual_rows.rdoc +217 -31
- data/lib/sequel/adapters/ado.rb +28 -12
- data/lib/sequel/adapters/ado/mssql.rb +33 -1
- data/lib/sequel/adapters/amalgalite.rb +13 -8
- data/lib/sequel/adapters/db2.rb +1 -2
- data/lib/sequel/adapters/dbi.rb +7 -4
- data/lib/sequel/adapters/do.rb +14 -15
- data/lib/sequel/adapters/do/postgres.rb +4 -5
- data/lib/sequel/adapters/do/sqlite.rb +9 -0
- data/lib/sequel/adapters/firebird.rb +5 -10
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +111 -49
- data/lib/sequel/adapters/jdbc/mssql.rb +1 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +4 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +8 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +12 -0
- data/lib/sequel/adapters/mysql.rb +14 -5
- data/lib/sequel/adapters/odbc.rb +2 -4
- data/lib/sequel/adapters/odbc/mssql.rb +2 -4
- data/lib/sequel/adapters/openbase.rb +1 -2
- data/lib/sequel/adapters/oracle.rb +4 -8
- data/lib/sequel/adapters/postgres.rb +4 -11
- data/lib/sequel/adapters/shared/mssql.rb +22 -9
- data/lib/sequel/adapters/shared/mysql.rb +33 -30
- data/lib/sequel/adapters/shared/oracle.rb +0 -5
- data/lib/sequel/adapters/shared/postgres.rb +13 -11
- data/lib/sequel/adapters/shared/sqlite.rb +56 -10
- data/lib/sequel/adapters/sqlite.rb +16 -9
- data/lib/sequel/connection_pool.rb +6 -1
- data/lib/sequel/connection_pool/single.rb +1 -0
- data/lib/sequel/core.rb +6 -1
- data/lib/sequel/database.rb +52 -23
- data/lib/sequel/database/schema_generator.rb +6 -0
- data/lib/sequel/database/schema_methods.rb +5 -5
- data/lib/sequel/database/schema_sql.rb +1 -1
- data/lib/sequel/dataset.rb +4 -190
- data/lib/sequel/dataset/actions.rb +323 -1
- data/lib/sequel/dataset/features.rb +18 -2
- data/lib/sequel/dataset/graph.rb +7 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +6 -0
- data/lib/sequel/dataset/query.rb +272 -6
- data/lib/sequel/dataset/sql.rb +186 -394
- data/lib/sequel/model.rb +4 -2
- data/lib/sequel/model/associations.rb +31 -14
- data/lib/sequel/model/base.rb +32 -13
- data/lib/sequel/model/exceptions.rb +8 -4
- data/lib/sequel/model/plugins.rb +3 -13
- data/lib/sequel/plugins/active_model.rb +26 -7
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/optimistic_locking.rb +25 -9
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +26 -0
- data/spec/adapters/mysql_spec.rb +33 -4
- data/spec/adapters/postgres_spec.rb +24 -1
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/adapters/sqlite_spec.rb +28 -0
- data/spec/core/connection_pool_spec.rb +17 -5
- data/spec/core/database_spec.rb +101 -1
- data/spec/core/dataset_spec.rb +42 -4
- data/spec/core/schema_spec.rb +13 -0
- data/spec/extensions/active_model_spec.rb +34 -11
- data/spec/extensions/caching_spec.rb +2 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/spec_helper.rb +2 -0
- data/spec/integration/dataset_test.rb +12 -1
- data/spec/integration/model_test.rb +12 -0
- data/spec/integration/plugin_test.rb +61 -1
- data/spec/integration/schema_test.rb +14 -3
- data/spec/model/base_spec.rb +27 -0
- data/spec/model/plugins_spec.rb +0 -22
- data/spec/model/record_spec.rb +32 -1
- data/spec/model/spec_helper.rb +2 -0
- metadata +14 -3
- data/lib/sequel/dataset/convenience.rb +0 -326
@@ -0,0 +1,106 @@
|
|
1
|
+
= Dataset Basics
|
2
|
+
|
3
|
+
== Introduction
|
4
|
+
|
5
|
+
Datasets are probably the thing that separate Sequel from other database libraries. While most database libraries have specific support for updating all records or only a single record, Sequel's ability to represent SQL queries themselves as objects is what gives Sequel most of its power. However, if you haven't been exposed to the dataset concept before, it can be a little disorienting. This document aims to give a basic introduction to datasets and how to use them.
|
6
|
+
|
7
|
+
== What a Dataset Represents
|
8
|
+
|
9
|
+
A Dataset can be thought of representing one of two concepts:
|
10
|
+
|
11
|
+
* An SQL query
|
12
|
+
* An abstract set of rows and some related behavior
|
13
|
+
|
14
|
+
The first concept is more easily understood, so you should probably start with that assumption.
|
15
|
+
|
16
|
+
== Basics
|
17
|
+
|
18
|
+
The most basic dataset is the simple selection of all columns in a table:
|
19
|
+
|
20
|
+
ds = DB[:posts]
|
21
|
+
# SELECT * FROM posts
|
22
|
+
|
23
|
+
Here, DB represents your Sequel::Database object, and ds is your dataset, with the SQL query it represents below it.
|
24
|
+
|
25
|
+
One of the core dataset ideas that should be understood is that datasets use a functional style of modification, in which methods called on the dataset return modified copies of the dataset, they don't modify the dataset themselves:
|
26
|
+
|
27
|
+
ds2 = ds.filter(:id=>1)
|
28
|
+
ds2
|
29
|
+
# SELECT * FROM posts WHERE id = 1
|
30
|
+
ds
|
31
|
+
# SELECT * FROM posts
|
32
|
+
|
33
|
+
Note how ds itself is not modified. This is because ds.filter returns a modified copy of ds, instead of modifying ds itself. This makes using datasets both thread safe and easy to chain:
|
34
|
+
|
35
|
+
# Thread safe:
|
36
|
+
100.times do |i|
|
37
|
+
Thread.new do
|
38
|
+
ds.filter(:id=>i).first
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Easy to chain:
|
43
|
+
ds3 = ds.select(:id, :name).order(:name).filter{id < 100}
|
44
|
+
# SELECT id, name FROM posts WHERE id < 100 ORDER BY name
|
45
|
+
|
46
|
+
Thread safety you don't really need to worry about, but chainability is core to how Sequel is generally used. Almost all dataset methods that affect the SQL produced return modified copies of the receiving dataset.
|
47
|
+
|
48
|
+
Another important thing to realize is that dataset methods that return modified datasets do not execute the dataset's code on the database. Only dataset methods that return or yield results will execute the code on the database:
|
49
|
+
|
50
|
+
# No SQL queries sent:
|
51
|
+
ds3 = ds.select(:id, :name).order(:name).filter{id < 100}
|
52
|
+
|
53
|
+
# Until you call a method that returns results
|
54
|
+
results = ds3.all
|
55
|
+
|
56
|
+
One important consequence of this API style is that if you use a method chain that includes both methods that return modified copies and a method that executes the SQL, the method that executes the SQL should generally be the last method in the chain:
|
57
|
+
|
58
|
+
# Good
|
59
|
+
ds.select(:id, :name).order(:name).filter{id < 100}.all
|
60
|
+
|
61
|
+
# Bad
|
62
|
+
ds.all.select(:id, :name).order(:name).filter{id < 100}
|
63
|
+
|
64
|
+
This is because all will return an array of hashes, and select, order, and filter are dataset methods, not array methods.
|
65
|
+
|
66
|
+
== Methods
|
67
|
+
|
68
|
+
Most Dataset methods that users will use can be broken down into two types:
|
69
|
+
|
70
|
+
* Methods that return modified datasets
|
71
|
+
* Methods that execute code on the database
|
72
|
+
|
73
|
+
=== Methods that return modified datasets
|
74
|
+
|
75
|
+
Most dataset methods fall into this category, which can be further broken down by the clause they affect:
|
76
|
+
|
77
|
+
SELECT:: select, select_all, select_append, select_more
|
78
|
+
FROM:: from, from_self
|
79
|
+
JOIN:: 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
|
83
|
+
ORDER:: order, order_by, order_more, reverse, reverse_order, unordered
|
84
|
+
LIMIT:: limit
|
85
|
+
compounds:: union, intersect, except
|
86
|
+
locking:: for_update, lock_style
|
87
|
+
common table expressions:: with, with_recursive
|
88
|
+
qualification:: qualify, qualify_to, qualify_to_first_source
|
89
|
+
inserting:: set_defaults, set_overrides
|
90
|
+
other:: clone, distinct, naked, server, with_sql
|
91
|
+
|
92
|
+
=== Methods that execute code on the database
|
93
|
+
|
94
|
+
Most other dataset methods commonly used will execute the dataset's SQL on the database:
|
95
|
+
|
96
|
+
SELECT (All Records):: all, each, map, to_hash, select_map, select_order_map, select_hash, to_csv
|
97
|
+
SELECT (First Record):: first, last, get, []
|
98
|
+
SELECT (Aggregates):: count, avg, max, min, sum, range, interval
|
99
|
+
INSERT:: insert, <<, import, multi_insert, insert_multiple
|
100
|
+
UPDATE:: update, set, []=
|
101
|
+
DELETE:: delete
|
102
|
+
other:: columns, columns!, truncate
|
103
|
+
|
104
|
+
=== Other methods
|
105
|
+
|
106
|
+
See the Sequel::Dataset RDoc for other methods that are less commonly used.
|
data/doc/opening_databases.rdoc
CHANGED
@@ -49,8 +49,8 @@ unless the first argument is a hash. So the following statements are equivalent
|
|
49
49
|
== Passing a block to either method
|
50
50
|
|
51
51
|
Both the Sequel.connect method and the specialized adapter methods take a block. If you
|
52
|
-
provide a block to the method, Sequel will
|
53
|
-
to the block. When the block
|
52
|
+
provide a block to the method, Sequel will create a Database object and pass it as an argument
|
53
|
+
to the block. When the block returns, Sequel will disconnect the database connection.
|
54
54
|
For example:
|
55
55
|
|
56
56
|
Sequel.connect('sqlite://blog.db'){|db| puts db[:users].count}
|
@@ -67,11 +67,13 @@ These options are shared by all adapters unless otherwise noted.
|
|
67
67
|
* :loggers - An array of SQL loggers to log to
|
68
68
|
* :password - The password for the user account
|
69
69
|
* :servers - A hash with symbol keys and hash or proc values, used with master/slave/partitioned database configurations
|
70
|
-
* :single_threaded - Whether to use
|
70
|
+
* :single_threaded - Whether to use a single-threaded (non-thread safe) connection pool
|
71
|
+
* :test - Whether to test that a valid database connection can be made (false by default)
|
71
72
|
* :user - The user account name to use logging in
|
72
73
|
|
73
74
|
The following options can be specified and are passed to the the database's internal connection pool.
|
74
75
|
|
76
|
+
* :after_connect - A proc called after a new connection is made, with the connection object (default: nil)
|
75
77
|
* :max_connections - The maximum size of the connection pool (default: 4 connections on most databases)
|
76
78
|
* :pool_sleep_time - The number of seconds to sleep before trying to acquire a connection again (default: 0.001 seconds)
|
77
79
|
* :pool_timeout - The number of seconds to wait if a connection cannot be acquired before raising an error (default: 5 seconds)
|
@@ -92,14 +94,24 @@ on WIN32OLE library, so it isn't usable on other operating systems (except
|
|
92
94
|
possibly through WINE, but that's fairly unlikely).
|
93
95
|
|
94
96
|
The following options are supported:
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
97
|
+
|
98
|
+
:command_timeout :: Sets the time in seconds to wait while attempting
|
99
|
+
to execute a command before cancelling the attempt and generating
|
100
|
+
an error. Specifically, it sets the ADO CommandTimeout property.
|
101
|
+
If this property is not set, the default of 30 seconds is used.
|
102
|
+
:driver :: The driver to use in the ADO connection string. If not provided, a default
|
103
|
+
of "SQL Server" is used.
|
104
|
+
:conn_string :: The full ADO connection string. If this is provided,
|
105
|
+
the usual options are ignored.
|
106
|
+
:provider :: Sets the Provider of this ADO connection (for example, "SQLOLEDB").
|
107
|
+
If you don't specify a provider, the default one used by WIN32OLE
|
108
|
+
has major problems, such as creating a new native database connection
|
109
|
+
for every query, which breaks things such as transactions and temporary tables.
|
110
|
+
|
111
|
+
Pay special attention to the :provider option, as without specifying a provider,
|
112
|
+
many things will be broken. The SQLNCLI10 provider appears to work well if you
|
113
|
+
are connecting to Microsoft SQL Server, but it is not the default as that would
|
114
|
+
break backwards compatability.
|
103
115
|
|
104
116
|
=== amalgalite
|
105
117
|
|
@@ -188,9 +200,9 @@ Requires: java
|
|
188
200
|
Houses Sequel's JDBC support when running on JRuby.
|
189
201
|
Support for individual database types is done using sub adapters.
|
190
202
|
There are currently subadapters for PostgreSQL, MySQL, SQLite, H2,
|
191
|
-
Oracle, and
|
192
|
-
|
193
|
-
or load the Java class manually.
|
203
|
+
Oracle, MSSQL, JTDS, and AS400. All except Oracle, MSSQL, and AS400 can load the
|
204
|
+
jdbc-* gem, for those you need to have the .jar in your CLASSPATH
|
205
|
+
or load the Java class manually before calling Sequel.connect.
|
194
206
|
|
195
207
|
You just use the JDBC connection string directly, which can be specified
|
196
208
|
via the string given to Sequel.connect or via the :uri, :url, or :database options.
|
@@ -198,12 +210,27 @@ Sequel does no preprocessing of the string, it passes it directly to JDBC.
|
|
198
210
|
So if you have problems getting a connection string to work, look up the JDBC
|
199
211
|
documentation.
|
200
212
|
|
201
|
-
|
213
|
+
Note that when using a JDBC adapter, the best way to use Sequel
|
214
|
+
is via Sequel.connect, NOT Sequel.jdbc. Use the JDBC connection
|
215
|
+
string when connecting, which will be in a different format than
|
216
|
+
the native connection string. The connection string should start
|
217
|
+
with 'jdbc:'. For PostgreSQL, use 'jdbc:postgresql:', and for
|
218
|
+
SQLite you do not need 2 preceding slashes for the database name
|
219
|
+
(use no preceding slashes for a relative path, and one preceding
|
220
|
+
slash for an absolute path).
|
221
|
+
|
222
|
+
Example connection strings:
|
202
223
|
|
203
224
|
jdbc:sqlite::memory:
|
204
225
|
jdbc:postgresql://localhost/database?user=username
|
205
226
|
jdbc:mysql://localhost/test?user=root&password=root
|
206
227
|
jdbc:h2:mem:
|
228
|
+
jdbc:sqlserver://localhost;database=sequel_test;integratedSecurity=true
|
229
|
+
jdbc:jtds:sqlserver://localhost/sequel_test;user=sequel_test;password=sequel_test
|
230
|
+
|
231
|
+
You can also use JNDI connection strings:
|
232
|
+
|
233
|
+
jdbc:jndi:java:comp/env/jndi_resource_name
|
207
234
|
|
208
235
|
The following additional options are supported:
|
209
236
|
|
@@ -214,7 +241,7 @@ The following additional options are supported:
|
|
214
241
|
|
215
242
|
=== mysql
|
216
243
|
|
217
|
-
The MySQL adapter does not support the pure-ruby MySQL adapter that
|
244
|
+
The MySQL adapter does not support the pure-ruby MySQL adapter that used to ship with
|
218
245
|
ActiveRecord, it requires the native adapter.
|
219
246
|
|
220
247
|
The following additional options are supported:
|
@@ -222,6 +249,8 @@ The following additional options are supported:
|
|
222
249
|
* :auto_is_null - If set to true, makes "WHERE primary_key IS NULL" select the last inserted id.
|
223
250
|
* :charset - Same as :encoding, :encoding takes precedence.
|
224
251
|
* :compress - Whether to compress data sent/received via the socket connection.
|
252
|
+
* :config_default_group - The default group to read from the in the MySQL config file.
|
253
|
+
* :config_local_infile - If provided, sets the Mysql::OPT_LOCAL_INFILE option on the connection with the given value.
|
225
254
|
* :encoding - Specify the encoding/character set to use for the connection.
|
226
255
|
* :socket - Can be used to specify a Unix socket file to connect to instead of a TCP host and port.
|
227
256
|
* :timeout - Sets the wait_timeout for the connection, defaults to 1 month.
|
data/doc/querying.rdoc
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
= Querying in Sequel
|
2
|
+
|
3
|
+
This guide is based on http://guides.rubyonrails.org/active_record_querying.html
|
4
|
+
|
5
|
+
== Purpose of this Guide
|
6
|
+
|
7
|
+
Sequel is a simple to use, very flexible, and powerful database library
|
8
|
+
that supports a wide variety of different querying methods. This guide
|
9
|
+
aims to be a gentle introduction to Sequel's querying support.
|
10
|
+
|
11
|
+
While you can easily use raw SQL with Sequel, a large part of the
|
12
|
+
advantage you get from using Sequel is Sequel's ability to abstract
|
13
|
+
SQL from you and give you a much nicer interface.
|
14
|
+
|
15
|
+
== Setup
|
16
|
+
|
17
|
+
Some examples in this guide assume you will be using Sequel::Model
|
18
|
+
for modeling, but most should work with plain datasets. The examples
|
19
|
+
specific to Sequel::Model will have [Sequel::Model] in the heading.
|
20
|
+
|
21
|
+
Many of the examples in this guide will refer to the following model
|
22
|
+
classes:
|
23
|
+
|
24
|
+
# All classes use :id as the primary key column
|
25
|
+
|
26
|
+
class Artist < Sequel::Model
|
27
|
+
one_to_many :albums
|
28
|
+
one_to_one :address
|
29
|
+
end
|
30
|
+
|
31
|
+
class Album < Sequel::Model
|
32
|
+
many_to_one :artist
|
33
|
+
one_to_many :tracks
|
34
|
+
many_to_many :tags
|
35
|
+
end
|
36
|
+
|
37
|
+
class Address < Sequel::Model
|
38
|
+
many_to_one :artist
|
39
|
+
end
|
40
|
+
|
41
|
+
class Tag < Sequel::Model
|
42
|
+
many_to_many :albums
|
43
|
+
end
|
44
|
+
|
45
|
+
class Track < Sequel::Model
|
46
|
+
many_to_one :album
|
47
|
+
end
|
48
|
+
|
49
|
+
If you want to play with the code examples, here's some Sequel code
|
50
|
+
that will set up the database structure for you:
|
51
|
+
|
52
|
+
DB.create_table(:artists) do
|
53
|
+
primary_key :id
|
54
|
+
String :name
|
55
|
+
end
|
56
|
+
|
57
|
+
DB.create_table(:albums) do
|
58
|
+
primary_key :id
|
59
|
+
foreign_key :artist_id, :artists
|
60
|
+
String :name
|
61
|
+
end
|
62
|
+
|
63
|
+
DB.create_table(:addresses) do
|
64
|
+
primary_key :id
|
65
|
+
foreign_key :artist_id, :artists, :unique=>true
|
66
|
+
String :street
|
67
|
+
String :city
|
68
|
+
String :state
|
69
|
+
String :zip
|
70
|
+
end
|
71
|
+
|
72
|
+
DB.create_table(:tags) do
|
73
|
+
primary_key :id
|
74
|
+
String :tag
|
75
|
+
end
|
76
|
+
|
77
|
+
DB.create_table(:albums_tags) do
|
78
|
+
foreign_key :album_id, :albums
|
79
|
+
foreign_key :tag_id, :tags
|
80
|
+
end
|
81
|
+
|
82
|
+
DB.create_table(:tracks) do
|
83
|
+
primary_key :id
|
84
|
+
foreign_key :album_id, :albums
|
85
|
+
Integer :number
|
86
|
+
String :name
|
87
|
+
end
|
88
|
+
|
89
|
+
== Retrieving Objects
|
90
|
+
|
91
|
+
Sequel provides a few separate methods for retrieving objects from the
|
92
|
+
database. The underlying method is Sequel::Dataset#each, which yields each
|
93
|
+
row as the Sequel::Database provides it. However, while Dataset#each can and
|
94
|
+
often is used directly, in many cases there is a more convenient retrieval
|
95
|
+
method you can use.
|
96
|
+
|
97
|
+
=== Sequel::Dataset
|
98
|
+
|
99
|
+
If you are new to Sequel and aren't familiar with Sequel, you should probably
|
100
|
+
read the {"Dataset Basics" guide}[link:files/doc/dataset_basics_rdoc.html],
|
101
|
+
then come back here.
|
102
|
+
|
103
|
+
=== Retrieving a Single Object
|
104
|
+
|
105
|
+
Sequel offers quite a few ways to to retrieve a single object.
|
106
|
+
|
107
|
+
==== Using a Primary Key [Sequel::Model]
|
108
|
+
|
109
|
+
The <tt>Sequel::Model.[]</tt> is the easiest method to use to find a model instance
|
110
|
+
by its primary key value:
|
111
|
+
|
112
|
+
# Find artist with primary key (id) 1
|
113
|
+
artist = Artist[1]
|
114
|
+
# SQL: SELECT * FROM artists WHERE id = 1
|
115
|
+
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
116
|
+
|
117
|
+
If there is no record with the given primary key, nil will be returned.
|
118
|
+
|
119
|
+
==== Using +first+
|
120
|
+
|
121
|
+
If you just want the first record in the dataset,
|
122
|
+
<tt>Sequel::Dataset#first</tt> is probably the most obvious method to use:
|
123
|
+
|
124
|
+
artist = Artist.first
|
125
|
+
# SQL: SELECT * FROM artists LIMIT 1
|
126
|
+
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
127
|
+
|
128
|
+
Any options you pass to +first+ will be used as a filter:
|
129
|
+
|
130
|
+
artist = Artist.first(:name => 'YJM')
|
131
|
+
# SQL: SELECT * FROM artists WHERE (name = 'YJM') LIMIT 1
|
132
|
+
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
133
|
+
|
134
|
+
artist = Artist.first(:name.like('Y%'))
|
135
|
+
# SQL: SELECT * FROM artists WHERE (name LIKE 'Y%') LIMIT 1
|
136
|
+
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
137
|
+
|
138
|
+
<tt>Sequel::Dataset#[]</tt> is basically an alias for +first+, except it
|
139
|
+
requires an argument:
|
140
|
+
|
141
|
+
DB[:artists][:name => 'YJM']
|
142
|
+
# SQL: SELECT * FROM artists WHERE (name = 'YJM') LIMIT 1
|
143
|
+
=> {:name=>"YJM", :id=>1}
|
144
|
+
|
145
|
+
Note that while Model.[] allows you to pass a primary key directly,
|
146
|
+
Dataset#[] does not.
|
147
|
+
|
148
|
+
==== Using +last+
|
149
|
+
|
150
|
+
If you want the last record in the dataset,
|
151
|
+
<tt>Sequel::Dataset#last</tt> is an obvious method to use. Note first
|
152
|
+
that last requires that the dataset be ordered. Without an order, any
|
153
|
+
object can be considered the first as well as the last.
|
154
|
+
|
155
|
+
artist = Artist.order(:name).last
|
156
|
+
# SQL: SELECT * FROM artists ORDER BY name DESC LIMIT 1
|
157
|
+
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
158
|
+
|
159
|
+
Note that all +last+ does is reverse the order of the dataset and then
|
160
|
+
call +first+. This is why +last+ raises a Sequel::Error if there is no
|
161
|
+
order on the dataset, because otherwise it would provide the same record
|
162
|
+
as +first+, and most users would fine that confusing.
|
163
|
+
|
164
|
+
Note that +last+ is not necessarily going to give you the last record
|
165
|
+
in the dataset unless you give the dataset an unambiguous order.
|
166
|
+
|
167
|
+
==== Retrieving a Single Column Value
|
168
|
+
|
169
|
+
Sometimes, intead of wanting an entire row, you only want the value of
|
170
|
+
a specific column. For this <tt>Sequel::Dataset#get</tt> is the method
|
171
|
+
you want:
|
172
|
+
|
173
|
+
artist_name = Artist.get(:name)
|
174
|
+
# SQL: SELECT name FROM artists LIMIT 1
|
175
|
+
=> "YJM"
|
176
|
+
|
177
|
+
=== Retrieving Multiple Objects
|
178
|
+
|
179
|
+
==== As a Array of Hashes or Model Objects
|
180
|
+
|
181
|
+
In many cases, you want an array of all of the rows associated with the
|
182
|
+
dataset, in which case <tt>Sequel::Dataset#all</tt> is the method you
|
183
|
+
want to use:
|
184
|
+
|
185
|
+
artists = Artist.all
|
186
|
+
# SQL: SELECT * FROM artists
|
187
|
+
=> [#<Artist @values={:name=>"YJM", :id=>1}>,
|
188
|
+
#<Artist @values={:name=>"AS", :id=>2}>]
|
189
|
+
|
190
|
+
==== Using an Enumerable Interface
|
191
|
+
|
192
|
+
<tt>Sequel::Dataset</tt> uses an Enumerable Interface, so it provides a
|
193
|
+
method named each that yields hashes or model objects as they are retrieved
|
194
|
+
from the database:
|
195
|
+
|
196
|
+
Artist.each{|x| p x.name}
|
197
|
+
# SQL: SELECT * FROM artists
|
198
|
+
"YJM"
|
199
|
+
"AS"
|
200
|
+
|
201
|
+
This means that all of the methods in the Enumerable module are available,
|
202
|
+
such as +map+:
|
203
|
+
|
204
|
+
artist_names = Artist.map{|x| x.name}
|
205
|
+
# SQL: SELECT * FROM artists
|
206
|
+
=> ["YJM", "AS"]
|
207
|
+
|
208
|
+
==== As an Array of Column Values
|
209
|
+
|
210
|
+
At 1.2.2 in Rails Guide
|
@@ -0,0 +1,254 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A few new features were added to query logging. Sequel now
|
4
|
+
includes execution time when logging queries. Queries that
|
5
|
+
raise exceptions are now logged at ERROR level. You can now
|
6
|
+
set the log_warn_duration attribute on the Database instance
|
7
|
+
and queries that take longer than that will be logged at WARN
|
8
|
+
level. By using different log levels, you can now only log
|
9
|
+
queries that raise errors, or only log queries that take a long
|
10
|
+
time.
|
11
|
+
|
12
|
+
# The default - Log all successful queries at INFO level
|
13
|
+
DB.log_warn_duration = nil
|
14
|
+
|
15
|
+
# Log all successful queries at WARN level
|
16
|
+
DB.log_warn_duration = 0
|
17
|
+
|
18
|
+
# Log successful queries that take the database more than half a
|
19
|
+
# second at WARN level, other successful queries at INFO level
|
20
|
+
DB.log_warn_duration = 0.5
|
21
|
+
|
22
|
+
All adapters included with Sequel have been modified to support
|
23
|
+
the new logging API. The previous API is still available, so
|
24
|
+
any external adapters should still work, though switching to the
|
25
|
+
new logging API is encouraged.
|
26
|
+
|
27
|
+
* Sequel::Model now has a require_modification flag. If not set
|
28
|
+
explicitly, it is enabled by default if the dataset provides an
|
29
|
+
accurate number of rows matched by an update or delete statement.
|
30
|
+
When this setting is enabled, Sequel will raise an exception if
|
31
|
+
you attempt to update or delete a model object and it doesn't end
|
32
|
+
up affecting exactly one row. For example:
|
33
|
+
|
34
|
+
DB.create_table(:as){primary_key :id}
|
35
|
+
class A < Sequel::Model; end
|
36
|
+
a = A.create
|
37
|
+
|
38
|
+
# delete object from database
|
39
|
+
a.delete
|
40
|
+
|
41
|
+
a.require_modification = false
|
42
|
+
a.save # no error!
|
43
|
+
a.delete # no error!
|
44
|
+
|
45
|
+
a.require_modification = true
|
46
|
+
a.save # Sequel::NoExistingObject exception raised
|
47
|
+
a.delete # Sequel::NoExistingObject exception raised
|
48
|
+
|
49
|
+
Like many other Sequel::Model settings, this can be set on a
|
50
|
+
global, per class, and per instance level:
|
51
|
+
|
52
|
+
Sequel::Model.require_modification = false # global
|
53
|
+
Album.require_modification = true # class
|
54
|
+
album.require_modification = false # instance
|
55
|
+
|
56
|
+
* An instance_filters plugin was added to the list of built in
|
57
|
+
plugins, allowing you to add arbitrary filters when updating or
|
58
|
+
destroying an instance. This allows you to continue using models
|
59
|
+
when previously you would have had to drop down to using datasets
|
60
|
+
to get the desired behavior:
|
61
|
+
|
62
|
+
class Item < Sequel::Model
|
63
|
+
plugin :instance_filters
|
64
|
+
end
|
65
|
+
|
66
|
+
# These are two separate objects that represent the same
|
67
|
+
# database row.
|
68
|
+
i1 = Item.first(:id=>1, :delete_allowed=>false)
|
69
|
+
i2 = Item.first(:id=>1, :delete_allowed=>false)
|
70
|
+
|
71
|
+
# Add an instance filter to the object. This filter is in effect
|
72
|
+
# until the object is successfully updated or deleted.
|
73
|
+
i1.instance_filter(:delete_allowed=>true)
|
74
|
+
|
75
|
+
# Attempting to delete the object where the filter doesn't
|
76
|
+
# match any rows raises an error.
|
77
|
+
i1.delete # raises Sequel::Error
|
78
|
+
|
79
|
+
# The other object that represents the same row has no
|
80
|
+
# instance filters, and can be updated normally.
|
81
|
+
i2.update(:delete_allowed=>true)
|
82
|
+
|
83
|
+
# Even though the filter is now still in effect, since the
|
84
|
+
# database row has been updated to allow deleting,
|
85
|
+
# delete now works.
|
86
|
+
i1.delete
|
87
|
+
|
88
|
+
* An :after_connect database option is now supported. If provided,
|
89
|
+
the option value should be a proc that takes a single argument.
|
90
|
+
It will be called with the underlying connection object before
|
91
|
+
connection object is added to the connection pool, allowing you
|
92
|
+
to set per connection options in a thread-safe manner.
|
93
|
+
|
94
|
+
This is useful for customizations you want set on every connection
|
95
|
+
that Sequel doesn't already support. For example, on PostgreSQL
|
96
|
+
if you wanted to set the schema search_path on every connection:
|
97
|
+
|
98
|
+
DB = Sequel.postgres('dbname', :after_connect=>(proc do |conn|
|
99
|
+
conn.execute('SET search_path TO schema1,schema2')
|
100
|
+
end))
|
101
|
+
|
102
|
+
* A :test database option is now supported. If set to true, it
|
103
|
+
automatically calls test_connection to make sure a connection can
|
104
|
+
be made before returning a Database instance. For backwards
|
105
|
+
compatibility reasons, this is not set to true by default, but it
|
106
|
+
is possible that the default will change in a future version of
|
107
|
+
Sequel.
|
108
|
+
|
109
|
+
* The Dataset#select_append method was added, which always appends
|
110
|
+
to the existing selected columns. It operates identically to
|
111
|
+
select_more, except in the case that no columns are currently
|
112
|
+
selected:
|
113
|
+
|
114
|
+
ds = DB[:a]
|
115
|
+
# SELECT * FROM items
|
116
|
+
ds.select_more({:id=>DB[:b].select(:a_id)}.as(:in_b))
|
117
|
+
# SELECT id IN (SELECT a_id FROM b) AS in_b FROM a
|
118
|
+
ds.select_append({:id=>DB[:b].select(:a_id)}.as(:in_b))
|
119
|
+
# SELECT *, id IN (SELECT a_id FROM b) AS in_b FROM a
|
120
|
+
|
121
|
+
* The Dataset#provides_accurate_rows_matched? method was added which
|
122
|
+
allows you to see if the dataset will return the actual number of
|
123
|
+
rows matched/affected by an update or delete call.
|
124
|
+
|
125
|
+
* Sequel will now emulate DISTINCT ON support using GROUP BY on
|
126
|
+
MySQL. On MySQL, GROUP BY is similar to DISTINCT ON, except that
|
127
|
+
the order of returned rows is not deterministic.
|
128
|
+
|
129
|
+
* Support for connecting to Microsoft SQL Server using the JTDS JDBC
|
130
|
+
driver was added to the jdbc adapter.
|
131
|
+
|
132
|
+
* JDNI connection strings are now supported in the JDBC adapter.
|
133
|
+
|
134
|
+
* The JDBC adapter should now work in situations where driver
|
135
|
+
auto-loading has problems, just as when using Tomcat or Trinidad.
|
136
|
+
|
137
|
+
* Sequel's JDBC adapter schema parsing now supports a :scale option,
|
138
|
+
useful for numeric/decimal columns.
|
139
|
+
|
140
|
+
* Sequel's schema parsing on Microsoft SQL Server now supports
|
141
|
+
:column_size and :scale options.
|
142
|
+
|
143
|
+
* When connecting to SQLite, a Database#sqlite_version method is
|
144
|
+
available that gives you the SQLite version as an integer (e.g.
|
145
|
+
30613 for 3.6.13).
|
146
|
+
|
147
|
+
= Other Improvements
|
148
|
+
|
149
|
+
* Sequel no longer raises an error if you give Dataset#filter or
|
150
|
+
related method an empty argument such as {}, [], or ''. This allows
|
151
|
+
code such as the following to work:
|
152
|
+
|
153
|
+
h = {}
|
154
|
+
h[:name] = name if name
|
155
|
+
h[:number] = number if number
|
156
|
+
ds = ds.filter(h)
|
157
|
+
|
158
|
+
Before, this would raise an error if both name and number were
|
159
|
+
nil.
|
160
|
+
|
161
|
+
* Numeric and decimal columns with a 0 scale are now treated as
|
162
|
+
integer columns by the model typecasting code, since such columns
|
163
|
+
cannot store non-integer values.
|
164
|
+
|
165
|
+
* Calling Database#disconnect when using the single threaded
|
166
|
+
connection pool no longer raises an error if there is no current
|
167
|
+
connection.
|
168
|
+
|
169
|
+
* When using the :ignore_index_errors options to
|
170
|
+
Database#create_table, correctly swallow errors raised by Sequel
|
171
|
+
due to the adapter not supporting the given index type.
|
172
|
+
|
173
|
+
* The JDBC adapter no longer leaks ResultSets when retrieving
|
174
|
+
metadata.
|
175
|
+
|
176
|
+
* You can now connect to PostgreSQL when using ruby 1.9 with the
|
177
|
+
-Ku switch.
|
178
|
+
|
179
|
+
* When using the native MySQL adapter, only tinyint(1) columns are
|
180
|
+
now returned as booleans when using the convert_tinyint_to_bool
|
181
|
+
setting (the default). Previously, all tinyint columns would
|
182
|
+
be converted to booleans if the setting was enabled.
|
183
|
+
|
184
|
+
* Correctly handle inserts returning the autogenerated keys when
|
185
|
+
using MySQL JDBC Driver version 5.1.12 with the jdbc adapter.
|
186
|
+
|
187
|
+
* The native MySQL adapter now supports :config_default_group and
|
188
|
+
:config_local_infile options.
|
189
|
+
|
190
|
+
* When connecting to SQLite, you can provide the :auto_vacuum,
|
191
|
+
:foreign_keys, :synchronous, and :temp_store options for
|
192
|
+
making the appropriate PRAGMA setting on the database in a
|
193
|
+
thread-safe manner. The previous thread-unsafe PRAGMA setting
|
194
|
+
methods are available, but their use is discouraged.
|
195
|
+
|
196
|
+
* Sequel will not enable savepoints when connecting to SQLite
|
197
|
+
unless the version is 3.6.8 or greater.
|
198
|
+
|
199
|
+
* Using limit with distinct now works correctly on Microsoft SQL
|
200
|
+
Server.
|
201
|
+
|
202
|
+
* Database#rename_table now works correctly on Microsoft SQL Server.
|
203
|
+
|
204
|
+
* If you specify an explicit :provider when using the ADO adapter,
|
205
|
+
transactions will now work correctly. The default :provider uses
|
206
|
+
a new native connection for each query, so it cannot work with
|
207
|
+
transactions, or things like temporary tables.
|
208
|
+
|
209
|
+
* If you specify an explicit :provider when connecting to Microsoft
|
210
|
+
SQL Server using the ADO adapter (e.g. SQLNCLI10 or SQLNCLI),
|
211
|
+
Sequel is now able to provide an accurate number of rows modified
|
212
|
+
and deleted.
|
213
|
+
|
214
|
+
* Using set_column_allow_null with a decimal column with a precision
|
215
|
+
and scale now works correctly when connecting to Microsoft SQL
|
216
|
+
Server.
|
217
|
+
|
218
|
+
* You can now connect to Microsoft SQL Server using the dbi adapter.
|
219
|
+
|
220
|
+
* Sequel now recognizes the NUMBER database type as a synonym for
|
221
|
+
NUMERIC and DECIMAL, which may help some Oracle users.
|
222
|
+
|
223
|
+
* Transactions can now be rolled back correctly when connecting to
|
224
|
+
Oracle via JDBC.
|
225
|
+
|
226
|
+
* The active_model plugin now supports ActiveModel 3.0.0beta2.
|
227
|
+
|
228
|
+
* Many documentation improvements were made, including the addition
|
229
|
+
of a dataset basics guide, an association basics guide, an expanded
|
230
|
+
virtual row guide, and the separation of the Sequel::Dataset RDoc
|
231
|
+
page into sections. Additional, the RDoc class/method
|
232
|
+
documentation now contains links to the appropriate guides.
|
233
|
+
|
234
|
+
= Backwards Compatibility
|
235
|
+
|
236
|
+
* When connecting to SQLite, Sequel now automatically sets the
|
237
|
+
foreign_keys PRAGMA to true, which will make SQLite 3.6.19+ use
|
238
|
+
database enforced foreign key constraints. If you do not want
|
239
|
+
the database to enforce the foreign key constraints, you should
|
240
|
+
use the :foreign_keys=>false option when connecting to the
|
241
|
+
database.
|
242
|
+
|
243
|
+
* Sequel no longer creates #{plugin_name}_opts class, instance, and
|
244
|
+
dataset methods for each plugin loaded. No built-in plugin used
|
245
|
+
them, and I couldn't find an external plugin that did either.
|
246
|
+
|
247
|
+
* The Model#associations method is no longer available if the
|
248
|
+
default Associations plugin is not loaded due to the
|
249
|
+
SEQUEL_NO_ASSOCIATIONS constant or environment variable being set.
|
250
|
+
|
251
|
+
* DISTINCT ON support is turned off by default, and only enabled when
|
252
|
+
using PostgreSQL, since that appears to be the only database that
|
253
|
+
supports it. Previously, it was enabled by default and most common
|
254
|
+
adapters turned it off.
|