sequel_core 1.5.1 → 2.0.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 +116 -0
- data/COPYING +19 -19
- data/README +83 -32
- data/Rakefile +9 -20
- data/bin/sequel +43 -112
- data/doc/cheat_sheet.rdoc +225 -0
- data/doc/dataset_filtering.rdoc +257 -0
- data/lib/sequel_core/adapters/adapter_skeleton.rb +4 -2
- data/lib/sequel_core/adapters/ado.rb +3 -1
- data/lib/sequel_core/adapters/db2.rb +4 -2
- data/lib/sequel_core/adapters/dbi.rb +127 -113
- data/lib/sequel_core/adapters/informix.rb +4 -2
- data/lib/sequel_core/adapters/jdbc.rb +5 -3
- data/lib/sequel_core/adapters/mysql.rb +112 -46
- data/lib/sequel_core/adapters/odbc.rb +5 -7
- data/lib/sequel_core/adapters/odbc_mssql.rb +12 -3
- data/lib/sequel_core/adapters/openbase.rb +3 -1
- data/lib/sequel_core/adapters/oracle.rb +11 -9
- data/lib/sequel_core/adapters/postgres.rb +261 -262
- data/lib/sequel_core/adapters/sqlite.rb +72 -22
- data/lib/sequel_core/connection_pool.rb +140 -73
- data/lib/sequel_core/core_ext.rb +201 -66
- data/lib/sequel_core/core_sql.rb +123 -153
- data/lib/sequel_core/database/schema.rb +156 -0
- data/lib/sequel_core/database.rb +321 -338
- data/lib/sequel_core/dataset/callback.rb +11 -12
- data/lib/sequel_core/dataset/convenience.rb +213 -240
- data/lib/sequel_core/dataset/pagination.rb +58 -43
- data/lib/sequel_core/dataset/parse_tree_sequelizer.rb +331 -0
- data/lib/sequel_core/dataset/query.rb +41 -0
- data/lib/sequel_core/dataset/schema.rb +15 -0
- data/lib/sequel_core/dataset/sequelizer.rb +41 -373
- data/lib/sequel_core/dataset/sql.rb +741 -632
- data/lib/sequel_core/dataset.rb +183 -168
- data/lib/sequel_core/deprecated.rb +1 -169
- data/lib/sequel_core/exceptions.rb +24 -19
- data/lib/sequel_core/migration.rb +44 -52
- data/lib/sequel_core/object_graph.rb +43 -42
- data/lib/sequel_core/pretty_table.rb +71 -76
- data/lib/sequel_core/schema/generator.rb +163 -105
- data/lib/sequel_core/schema/sql.rb +250 -93
- data/lib/sequel_core/schema.rb +2 -8
- data/lib/sequel_core/sql.rb +394 -0
- data/lib/sequel_core/worker.rb +37 -27
- data/lib/sequel_core.rb +99 -45
- data/spec/adapters/informix_spec.rb +0 -1
- data/spec/adapters/mysql_spec.rb +177 -124
- data/spec/adapters/oracle_spec.rb +0 -1
- data/spec/adapters/postgres_spec.rb +98 -58
- data/spec/adapters/sqlite_spec.rb +45 -4
- data/spec/blockless_filters_spec.rb +269 -0
- data/spec/connection_pool_spec.rb +21 -18
- data/spec/core_ext_spec.rb +169 -19
- data/spec/core_sql_spec.rb +56 -49
- data/spec/database_spec.rb +78 -17
- data/spec/dataset_spec.rb +300 -428
- data/spec/migration_spec.rb +1 -1
- data/spec/object_graph_spec.rb +5 -11
- data/spec/rcov.opts +1 -1
- data/spec/schema_generator_spec.rb +16 -4
- data/spec/schema_spec.rb +89 -10
- data/spec/sequelizer_spec.rb +56 -56
- data/spec/spec.opts +0 -5
- data/spec/spec_config.rb +7 -0
- data/spec/spec_config.rb.example +5 -5
- data/spec/spec_helper.rb +6 -0
- data/spec/worker_spec.rb +1 -1
- metadata +78 -63
data/CHANGELOG
CHANGED
@@ -1,3 +1,119 @@
|
|
1
|
+
=== 2.0.0 (2008-06-01)
|
2
|
+
|
3
|
+
* Refactor String inflection support, you must use String.inflections instead of Inflector.inflections now (jeremyevans)
|
4
|
+
|
5
|
+
* Allow connection to ODBC-MSSQL via a URL (petersumskas) (#230)
|
6
|
+
|
7
|
+
* Comprehensive update of all documentation, except for the block filters and adapters (jeremyevans)
|
8
|
+
|
9
|
+
* Handle Date and DateTime value literalization correctly in adapters (jeremyevans)
|
10
|
+
|
11
|
+
* Literalize DateTime values the same as Time values (jeremyevans)
|
12
|
+
|
13
|
+
* MySQL tinyints are now returned as boolean values instead of integers (jeremyevans)
|
14
|
+
|
15
|
+
* Set additional MySQL charset options required for creating tables and databases (tmm1)
|
16
|
+
|
17
|
+
* Remove methods deprecated in 1.5.0 (jeremyevans)
|
18
|
+
|
19
|
+
* Add Module#metaattr_accessor for creating attr_accessors for the metaclass (jeremyevans)
|
20
|
+
|
21
|
+
* Add SQL string concatenation support to blockless filters, via Array#sql_string_join (jeremyevans)
|
22
|
+
|
23
|
+
* Add Pagination#last_page? and Pagination#first_page? (apeiros)
|
24
|
+
|
25
|
+
* Add limited column reflection support, tested on PostgreSQL, MySQL, and SQLite (jeremyevans)
|
26
|
+
|
27
|
+
* Allow the use of :schema__table___table_alias syntax for tables, similar to the column support (jeremyevans)
|
28
|
+
|
29
|
+
* Merge metaid gem into core_ext.rb and clean it up, so sequel now has no external dependencies (jeremyevans)
|
30
|
+
|
31
|
+
* Add Dataset#as, so using a dataset as a column with an alias is not deprecated (jeremyevans)
|
32
|
+
|
33
|
+
* Add Dataset#invert, which returns a dataset with inverted HAVING and WHERE clauses (jeremyevans)
|
34
|
+
|
35
|
+
* Add blockless filter syntax support (jeremyevans)
|
36
|
+
|
37
|
+
* Passing an array to Dataset#order and Dataset#select no longer works, you need to pass multiple arguments (jeremyevans)
|
38
|
+
|
39
|
+
* You should use '?' instead of '(?)' when using interpolated strings with array arguments (jeremyevans)
|
40
|
+
|
41
|
+
* Dataset.literal now surrounds the literalization of arrays with parentheses (jeremyevans)
|
42
|
+
|
43
|
+
* Add echo option (back?) to sequel command line tool, via -E or --echo (jeremyevans)
|
44
|
+
|
45
|
+
* Allow databases to have multiple loggers (jeremyevans)
|
46
|
+
|
47
|
+
* The sequel command line tool now also accepts a path to a database config YAML file in addition to a URI (mtodd)
|
48
|
+
|
49
|
+
* Major update of the postgresql adapter (jdavis, jeremyevans) (#225)
|
50
|
+
|
51
|
+
* Make returning inside of a database transaction commit the transaction (ahoward, jeremyevans)
|
52
|
+
|
53
|
+
* Dataset#to_table_reference is now protected, and it has a different API (jeremyevans)
|
54
|
+
|
55
|
+
* Dataset#join_table and related functions now take an explicit optional table_alias argument, you can no longer include the table alias in the table argument (jeremyevans)
|
56
|
+
|
57
|
+
* Aliased and/or qualified columns with embedded spaces can now be specified as symbols (jeremyevans)
|
58
|
+
|
59
|
+
* When identifier quoting is enabled, the SQL standard double quote is used by default (jeremyevans)
|
60
|
+
|
61
|
+
* When identifier quoting is enabled, quote tables as well as columns (jeremyevans)
|
62
|
+
|
63
|
+
* Make identifier quoting optional, enabled by default (jeremyevans)
|
64
|
+
|
65
|
+
* Allow Sequel::Database.connect and related methods to take a block that disconnects the database when the block finishes (jeremyevans)
|
66
|
+
|
67
|
+
* Add Dataset#unfiltered, for removing filters from dataset (jeremyevans)
|
68
|
+
|
69
|
+
* Add add_foreign_key and add_primary_key methods to the AlterTableGenerator (jeremyevans)
|
70
|
+
|
71
|
+
* Allow migration files to have more than 3 digits (jeremyevans)
|
72
|
+
|
73
|
+
* Add methods directly to Dataset instead of including modules (jeremyevans)
|
74
|
+
|
75
|
+
* Make some Dataset instance methods private: invert_order, insert_default_values_sql (jeremyevans)
|
76
|
+
|
77
|
+
* Don't add methods that depend on ParseTree unless you can load ParseTree (jeremyevans)
|
78
|
+
|
79
|
+
* Don't wipeout the cached columns every time a dataset is cloned, but only on changes to :select, :sql, :from, or :join (jeremyevans)
|
80
|
+
|
81
|
+
* Fix Oracle Adapter (yasushi.abe)
|
82
|
+
|
83
|
+
* Fixed sqlite uri so that sqlite:// works just like file:// (2 slashes for a relative path, 3 for an absolute) (dlee)
|
84
|
+
|
85
|
+
* Raise a Sequel::Error if an invalid limit or offset is used (jeremyevans)
|
86
|
+
|
87
|
+
* Refactor and beef up Dataset#first and Dataset#last, with some change in functionality (jeremyevans)
|
88
|
+
|
89
|
+
* Add String#to_datetime, for consistency (jeremyevans)
|
90
|
+
|
91
|
+
* Fix Range#interval so that it returns 1 less for an exclusive range
|
92
|
+
|
93
|
+
* Change SQLite adapter so it doesn't swallow exceptions other than SQLite3::Exception (such as Interrupt) (jeremyevans)
|
94
|
+
|
95
|
+
* Change PostgreSQL and MySQL adapters to raise Sequel::Error instead of database specific errors if a database error occurs (jeremyevans)
|
96
|
+
|
97
|
+
* Using a memory database with SQLite now defaults to a single connection, so all queries it uses run against the same database (jeremyevans)
|
98
|
+
|
99
|
+
* Fix attempting to query MySQL using the same connection being used to concurrently execute another query (jeremyevans)
|
100
|
+
|
101
|
+
* Add options to the connection pool to configure reusing connections and converting exceptions (jeremyevans)
|
102
|
+
|
103
|
+
* Use the database driver provided string quoting methods for MySQL and SQLite (jeremyevans) (#223)
|
104
|
+
|
105
|
+
* Add ColumnAll#==, for checking the equality of two ColumnAlls (jeremyevans)
|
106
|
+
|
107
|
+
* Allow an array of arrays instead of a hash when specifying conditions (jeremyevans)
|
108
|
+
|
109
|
+
* Add Sequel::DBI::Database#lowercase, for lowercasing column names (jamesearl)
|
110
|
+
|
111
|
+
* Remove Dataset#extend_with_destroy, which may break code that uses Dataset#set_model directly and expects the destroy method to be added (jeremyevans)
|
112
|
+
|
113
|
+
* Fix some issues when running on Ruby 1.9 (Zverok, jeremyevans)
|
114
|
+
|
115
|
+
* Make the DBI adapter work (partially) with PostgreSQL (Seb)
|
116
|
+
|
1
117
|
=== 1.5.1 (2008-04-30)
|
2
118
|
|
3
119
|
* Have Dataset#graph give a nil value instead of a hash with all nil values if no matching rows exist in the graphed table (jeremyevans)
|
data/COPYING
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
Copyright (c) 2007-2008 Sharon Rosner
|
2
|
-
Copyright (c) 2008 Jeremy Evans
|
3
|
-
|
4
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
-
of this software and associated documentation files (the "Software"), to
|
6
|
-
deal in the Software without restriction, including without limitation the
|
7
|
-
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
8
|
-
sell copies of the Software, and to permit persons to whom the Software is
|
9
|
-
furnished to do so, subject to the following conditions:
|
10
|
-
|
11
|
-
The above copyright notice and this permission notice shall be included in
|
12
|
-
all copies or substantial portions of the Software.
|
13
|
-
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
17
|
-
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
|
+
Copyright (c) 2007-2008 Sharon Rosner
|
2
|
+
Copyright (c) 2008 Jeremy Evans
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
of this software and associated documentation files (the "Software"), to
|
6
|
+
deal in the Software without restriction, including without limitation the
|
7
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
8
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
9
|
+
furnished to do so, subject to the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included in
|
12
|
+
all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
17
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
CHANGED
@@ -6,7 +6,6 @@ Sequel makes it easy to deal with multiple records without having to break your
|
|
6
6
|
|
7
7
|
== Resources
|
8
8
|
|
9
|
-
* {Project page}[http://code.google.com/p/ruby-sequel/]
|
10
9
|
* {Source code}[http://github.com/jeremyevans/sequel]
|
11
10
|
* {Bug tracking}[http://code.google.com/p/ruby-sequel/issues/list]
|
12
11
|
* {Google group}[http://groups.google.com/group/sequel-talk]
|
@@ -40,11 +39,39 @@ Sequel currently supports:
|
|
40
39
|
|
41
40
|
There are also experimental adapters for DB2, OpenBase and JDBC (on JRuby).
|
42
41
|
|
42
|
+
== A Short Example
|
43
|
+
|
44
|
+
require 'rubygems'
|
45
|
+
require 'sequel'
|
46
|
+
|
47
|
+
DB = Sequel.sqlite # memory database
|
48
|
+
|
49
|
+
DB.create_table :items do # Create a new table
|
50
|
+
column :name, :text
|
51
|
+
column :price, :float
|
52
|
+
end
|
53
|
+
|
54
|
+
items = DB[:items] # Create a dataset
|
55
|
+
|
56
|
+
# Populate the table
|
57
|
+
items << {:name => 'abc', :price => rand * 100}
|
58
|
+
items << {:name => 'def', :price => rand * 100}
|
59
|
+
items << {:name => 'ghi', :price => rand * 100}
|
60
|
+
|
61
|
+
# Print out the number of records
|
62
|
+
puts "Item count: #{items.count}"
|
63
|
+
|
64
|
+
# Print out the records in descending order by price
|
65
|
+
items.reverse_order(:price).print
|
66
|
+
|
67
|
+
# Print out the average price
|
68
|
+
puts "The average price is: #{items.avg(:price)}"
|
69
|
+
|
43
70
|
== The Sequel Console
|
44
71
|
|
45
72
|
Sequel includes an IRB console for quick'n'dirty access to databases. You can use it like this:
|
46
73
|
|
47
|
-
sequel sqlite
|
74
|
+
sequel sqlite://test.db # test.db in current directory
|
48
75
|
|
49
76
|
You get an IRB session with the database object stored in DB.
|
50
77
|
|
@@ -75,8 +102,6 @@ Or getting results as a transposed hash, with one column as key and another as v
|
|
75
102
|
|
76
103
|
middle_east.to_hash(:name, :area) #=> {'Israel' => 20000, 'Greece' => 120000, ...}
|
77
104
|
|
78
|
-
Much of Sequel is still undocumented (especially the part relating to model classes). The following section provides examples of common usage. Feel free to explore...
|
79
|
-
|
80
105
|
== Getting Started
|
81
106
|
|
82
107
|
=== Connecting to a database
|
@@ -84,16 +109,20 @@ Much of Sequel is still undocumented (especially the part relating to model clas
|
|
84
109
|
To connect to a database you simply provide Sequel with a URL:
|
85
110
|
|
86
111
|
require 'sequel'
|
87
|
-
DB = Sequel.
|
112
|
+
DB = Sequel.connect('sqlite://blog.db')
|
88
113
|
|
89
114
|
The connection URL can also include such stuff as the user name and password:
|
90
115
|
|
91
|
-
DB = Sequel.
|
116
|
+
DB = Sequel.connect('postgres://cico:12345@localhost:5432/mydb')
|
117
|
+
|
118
|
+
You can also specify optional parameters, such as the connection pool size, or loggers for logging SQL queries:
|
92
119
|
|
93
|
-
|
120
|
+
DB = Sequel.connect("postgres://postgres:postgres@localhost/my_db",
|
121
|
+
:max_connections => 10, :loggers => [Logger.new('log/db.log']))
|
94
122
|
|
95
|
-
|
96
|
-
|
123
|
+
You can specify a block to connect, which will disconnect from the database after it completes:
|
124
|
+
|
125
|
+
Sequel.connect('postgres://cico:12345@localhost:5432/mydb'){|db| db[:posts].delete}
|
97
126
|
|
98
127
|
=== Arbitrary SQL queries
|
99
128
|
|
@@ -105,6 +134,18 @@ Or more succinctly:
|
|
105
134
|
DB << "create table t (a text, b text)"
|
106
135
|
DB << "insert into t values ('a', 'b')"
|
107
136
|
|
137
|
+
You can also create datasets based on raw SQL:
|
138
|
+
|
139
|
+
dataset = DB['select * from items']
|
140
|
+
dataset.count # will return the number of records in the result set
|
141
|
+
dataset.map(:id) # will return an array containing all values of the id column in the result set
|
142
|
+
|
143
|
+
You can also fetch records with raw SQL through the dataset:
|
144
|
+
|
145
|
+
DB['select * from items'].each do |row|
|
146
|
+
p row
|
147
|
+
end
|
148
|
+
|
108
149
|
=== Getting Dataset Instances
|
109
150
|
|
110
151
|
Dataset is the primary means through which records are retrieved and manipulated. You can create an blank dataset by using the dataset method:
|
@@ -115,11 +156,11 @@ Or by using the from methods:
|
|
115
156
|
|
116
157
|
posts = DB.from(:posts)
|
117
158
|
|
118
|
-
|
159
|
+
The recommended way is the equivalent shorthand:
|
119
160
|
|
120
161
|
posts = DB[:posts]
|
121
162
|
|
122
|
-
|
163
|
+
Datasets will only fetch records when you explicitly ask for them. Datasets can be manipulated to filter through records, change record order, join tables, etc..
|
123
164
|
|
124
165
|
=== Retrieving Records
|
125
166
|
|
@@ -131,12 +172,12 @@ The all method returns an array of hashes, where each hash corresponds to a reco
|
|
131
172
|
|
132
173
|
You can also iterate through records one at a time:
|
133
174
|
|
134
|
-
posts.each
|
175
|
+
posts.each{|row| p row}
|
135
176
|
|
136
177
|
Or perform more advanced stuff:
|
137
178
|
|
138
179
|
posts.map(:id)
|
139
|
-
posts.inject({})
|
180
|
+
posts.inject({}){|h, r| h[r[:id]] = r[:name]}
|
140
181
|
|
141
182
|
You can also retrieve the first record in a dataset:
|
142
183
|
|
@@ -164,13 +205,9 @@ Or lists of values:
|
|
164
205
|
|
165
206
|
my_posts = posts.filter(:category => ['ruby', 'postgres', 'linux'])
|
166
207
|
|
167
|
-
|
168
|
-
|
169
|
-
my_posts = posts.filter {:category == ['ruby', 'postgres', 'linux']}
|
208
|
+
Sequel also accepts expressions:
|
170
209
|
|
171
|
-
|
172
|
-
|
173
|
-
my_posts = posts.filter {:stamp > Date.today << 1}
|
210
|
+
my_posts = posts.filter(:stamp > Date.today << 1)
|
174
211
|
|
175
212
|
Some adapters (like postgresql) will also let you specify Regexps:
|
176
213
|
|
@@ -179,19 +216,27 @@ Some adapters (like postgresql) will also let you specify Regexps:
|
|
179
216
|
You can also use an inverse filter:
|
180
217
|
|
181
218
|
my_posts = posts.exclude(:category => /ruby/i)
|
219
|
+
my_posts = posts.filter(:category => /ruby/i).invert # same as above
|
182
220
|
|
183
|
-
You can
|
221
|
+
You can also specify a custom WHERE clause using a string:
|
184
222
|
|
185
|
-
|
186
|
-
|
187
|
-
You can
|
223
|
+
posts.filter('stamp IS NOT NULL')
|
224
|
+
|
225
|
+
You can use parameters in your string, as well (ActiveRecord style):
|
188
226
|
|
189
|
-
posts.filter('(stamp < ?) AND (author
|
227
|
+
posts.filter('(stamp < ?) AND (author != ?)', Date.today - 3, author_name)
|
228
|
+
posts.filter((:stamp < Date.today - 3) & ~(:author => author_name)) # same as above
|
190
229
|
|
191
230
|
Datasets can also be used as subqueries:
|
192
231
|
|
193
232
|
DB[:items].filter('price > ?', DB[:items].select('AVG(price) + 100'))
|
194
233
|
|
234
|
+
After filtering you can retrieve the matching records by using any of the retrieval methods:
|
235
|
+
|
236
|
+
my_posts.each{|row| p row}
|
237
|
+
|
238
|
+
See the doc/dataset_filtering.rdoc file for more details.
|
239
|
+
|
195
240
|
=== Summarizing Records
|
196
241
|
|
197
242
|
Counting records is easy:
|
@@ -205,26 +250,32 @@ Or calculate a sum:
|
|
205
250
|
|
206
251
|
=== Ordering Records
|
207
252
|
|
208
|
-
|
253
|
+
Ordering datasets is simple:
|
254
|
+
|
255
|
+
posts.order(:stamp) # ORDER BY stamp
|
256
|
+
posts.order(:stamp, :name) # ORDER BY stamp, name
|
209
257
|
|
210
258
|
You can also specify descending order
|
211
259
|
|
212
|
-
posts.order(:stamp.desc)
|
260
|
+
posts.order(:stamp.desc) # ORDER BY stamp DESC
|
213
261
|
|
214
262
|
=== Deleting Records
|
215
263
|
|
264
|
+
Deleting records from the table is done with delete:
|
265
|
+
|
216
266
|
posts.filter('stamp < ?', Date.today - 3).delete
|
217
267
|
|
218
268
|
=== Inserting Records
|
219
269
|
|
220
|
-
|
221
|
-
|
222
|
-
Or alternatively:
|
270
|
+
Inserting records into the table is done with insert:
|
223
271
|
|
224
|
-
posts
|
272
|
+
posts.insert(:category => 'ruby', :author => 'david')
|
273
|
+
posts << {:category => 'ruby', :author => 'david'} # same as above
|
225
274
|
|
226
275
|
=== Updating Records
|
227
276
|
|
277
|
+
Updating records in the table is done with update:
|
278
|
+
|
228
279
|
posts.filter('stamp < ?', Date.today - 7).update(:state => 'archived')
|
229
280
|
|
230
281
|
=== Joining Tables
|
@@ -257,7 +308,7 @@ When retrieving records from joined datasets, you get the results in a single ha
|
|
257
308
|
DB[:items].join(:order_items, :item_id => :id).first
|
258
309
|
=> {:id=>(could be items.id or order_items.id), :item_id=>order_items.order_id}
|
259
310
|
|
260
|
-
Using graph, you can split the
|
311
|
+
Using graph, you can split the result hashes into subhashes, one per join:
|
261
312
|
|
262
313
|
DB[:items].graph(:order_items, :item_id => :id).first
|
263
|
-
=> {:items
|
314
|
+
=> {:items=>{:id=>items.id}, :order_items=>{:id=>order_items.id, :item_id=>order_items.item_id}}
|
data/Rakefile
CHANGED
@@ -9,19 +9,19 @@ include FileUtils
|
|
9
9
|
# Configuration
|
10
10
|
##############################################################################
|
11
11
|
NAME = "sequel_core"
|
12
|
-
VERS = "
|
13
|
-
CLEAN.include ["**/.*.sw?", "pkg
|
14
|
-
RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source"
|
12
|
+
VERS = "2.0.0"
|
13
|
+
CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage"]
|
14
|
+
RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
|
15
|
+
'Sequel: The Database Toolkit for Ruby: Core Library and Adapters', \
|
16
|
+
'--main', 'README']
|
15
17
|
|
16
18
|
##############################################################################
|
17
19
|
# RDoc
|
18
20
|
##############################################################################
|
19
21
|
Rake::RDocTask.new do |rdoc|
|
20
|
-
rdoc.rdoc_dir = "
|
22
|
+
rdoc.rdoc_dir = "rdoc"
|
21
23
|
rdoc.options += RDOC_OPTS
|
22
|
-
rdoc.
|
23
|
-
rdoc.title = "Sequel: The Database Toolkit for Ruby: Core Library and Adapters"
|
24
|
-
rdoc.rdoc_files.add ["README", "COPYING", "lib/**/*.rb"]
|
24
|
+
rdoc.rdoc_files.add ["README", "COPYING", "doc/*.rdoc", "lib/**/*.rb"]
|
25
25
|
end
|
26
26
|
|
27
27
|
##############################################################################
|
@@ -36,7 +36,7 @@ spec = Gem::Specification.new do |s|
|
|
36
36
|
s.version = VERS
|
37
37
|
s.platform = Gem::Platform::RUBY
|
38
38
|
s.has_rdoc = true
|
39
|
-
s.extra_rdoc_files = ["README", "CHANGELOG", "COPYING"]
|
39
|
+
s.extra_rdoc_files = ["README", "CHANGELOG", "COPYING"] + Dir["doc/*.rdoc"]
|
40
40
|
s.rdoc_options += RDOC_OPTS + ["--exclude", "^(examples|extras)\/"]
|
41
41
|
s.summary = "The Database Toolkit for Ruby: Core Library and Adapters"
|
42
42
|
s.description = s.summary
|
@@ -45,18 +45,7 @@ spec = Gem::Specification.new do |s|
|
|
45
45
|
s.homepage = "http://sequel.rubyforge.org"
|
46
46
|
s.executables = ["sequel"]
|
47
47
|
s.required_ruby_version = ">= 1.8.4"
|
48
|
-
|
49
|
-
s.add_dependency("metaid")
|
50
|
-
|
51
|
-
case RUBY_PLATFORM
|
52
|
-
when /java/
|
53
|
-
s.platform = "jruby"
|
54
|
-
else
|
55
|
-
s.platform = Gem::Platform::RUBY
|
56
|
-
end
|
57
|
-
|
58
48
|
s.files = %w(COPYING README Rakefile) + Dir.glob("{bin,doc,spec,lib}/**/*")
|
59
|
-
|
60
49
|
s.require_path = "lib"
|
61
50
|
s.bindir = "bin"
|
62
51
|
end
|
@@ -162,7 +151,7 @@ STATS_DIRECTORIES = [
|
|
162
151
|
|
163
152
|
desc "Report code statistics (KLOCs, etc) from the application"
|
164
153
|
task :stats do
|
165
|
-
require "extra/stats"
|
154
|
+
require "../extra/stats"
|
166
155
|
verbose = true
|
167
156
|
CodeStatistics.new(*STATS_DIRECTORIES).to_s
|
168
157
|
end
|
data/bin/sequel
CHANGED
@@ -2,35 +2,43 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'optparse'
|
5
|
-
require 'sequel' rescue nil
|
6
5
|
require 'sequel_core'
|
7
|
-
require 'sequel_model' rescue nil
|
8
|
-
require 'logger'
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
begin
|
8
|
+
require 'sequel'
|
9
|
+
sequel_loaded = true
|
10
|
+
rescue LoadError
|
11
|
+
end
|
12
|
+
|
13
|
+
db_opts = {}
|
14
|
+
echo = nil
|
15
|
+
env = nil
|
16
|
+
logfile = nil
|
13
17
|
|
14
18
|
opts = OptionParser.new do |opts|
|
15
19
|
opts.banner = "Sequel: The Database Toolkit for Ruby"
|
16
|
-
opts.define_head "Usage: sequel <uri> [options]"
|
20
|
+
opts.define_head "Usage: sequel <uri|path> [options]"
|
17
21
|
opts.separator ""
|
18
22
|
opts.separator "Examples:"
|
19
23
|
opts.separator " sequel sqlite:///blog.db"
|
20
24
|
opts.separator " sequel postgres://localhost/my_blog"
|
21
|
-
|
25
|
+
opts.separator " sequel config/database.yml"
|
22
26
|
opts.separator ""
|
23
|
-
opts.separator "For more information see http://
|
27
|
+
opts.separator "For more information see http://sequel.rubyforge.org"
|
24
28
|
opts.separator ""
|
25
29
|
opts.separator "Options:"
|
26
30
|
|
27
31
|
opts.on("-l", "--log logfile", "log SQL statements to log file") do |v|
|
28
|
-
|
32
|
+
logfile = v
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-E", "--echo", "echo SQL statements") do |v|
|
36
|
+
echo = v
|
29
37
|
end
|
30
38
|
|
31
|
-
|
32
|
-
|
33
|
-
|
39
|
+
opts.on("-e", "--env ENV", "use environment config for database") do |env|
|
40
|
+
env = env
|
41
|
+
end
|
34
42
|
|
35
43
|
opts.on_tail("-?", "--help", "Show this message") do
|
36
44
|
puts opts
|
@@ -39,14 +47,15 @@ opts = OptionParser.new do |opts|
|
|
39
47
|
|
40
48
|
opts.on_tail("-v", "--version", "Show version") do
|
41
49
|
class << Gem; attr_accessor :loaded_specs; end
|
42
|
-
|
43
|
-
puts "sequel #{specs.version} (#{specs.date.strftime '%Y-%m-%d'})"
|
50
|
+
begin
|
44
51
|
specs = Gem.loaded_specs['sequel_core']
|
45
52
|
puts "sequel_core #{specs.version} (#{specs.date.strftime '%Y-%m-%d'})"
|
46
|
-
|
47
|
-
specs = Gem.loaded_specs['
|
48
|
-
puts "
|
53
|
+
if sequel_loaded
|
54
|
+
specs = Gem.loaded_specs['sequel']
|
55
|
+
puts "sequel #{specs.version} (#{specs.date.strftime '%Y-%m-%d'})"
|
56
|
+
end
|
49
57
|
rescue
|
58
|
+
puts "No gem version found"
|
50
59
|
end
|
51
60
|
exit
|
52
61
|
end
|
@@ -60,23 +69,27 @@ if db.blank?
|
|
60
69
|
exit
|
61
70
|
end
|
62
71
|
|
63
|
-
|
64
|
-
|
65
|
-
db_opts[:
|
66
|
-
|
67
|
-
if
|
68
|
-
db_opts[:echo] = true
|
72
|
+
if logfile || echo
|
73
|
+
require 'logger'
|
74
|
+
db_opts[:loggers] = []
|
75
|
+
db_opts[:loggers] << Logger.new(logfile) if logfile
|
76
|
+
db_opts[:loggers] << Logger.new($stdout) if echo
|
69
77
|
end
|
70
78
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
exit
|
79
|
+
if File.exist?(db)
|
80
|
+
require 'yaml'
|
81
|
+
db_config = YAML.load_file(db)[env || "development"]
|
82
|
+
db_config.each {|(k,v)| db_config[k.to_sym] = db_config.delete(k)}
|
83
|
+
db_config.merge!(db_opts)
|
77
84
|
end
|
78
85
|
|
79
86
|
begin
|
87
|
+
if db_config
|
88
|
+
opts = [db_config]
|
89
|
+
else
|
90
|
+
opts = [db, db_opts]
|
91
|
+
end
|
92
|
+
DB = Sequel.connect(*opts)
|
80
93
|
DB.test_connection
|
81
94
|
rescue => e
|
82
95
|
puts e.message
|
@@ -87,85 +100,3 @@ end
|
|
87
100
|
require 'irb'
|
88
101
|
puts "Your database is stored in DB..."
|
89
102
|
IRB.start
|
90
|
-
|
91
|
-
__END__
|
92
|
-
|
93
|
-
#!/usr/bin/env ruby
|
94
|
-
|
95
|
-
require 'rubygems'
|
96
|
-
require 'optparse'
|
97
|
-
require 'bulkmail'
|
98
|
-
|
99
|
-
$helo = nil
|
100
|
-
$from = nil
|
101
|
-
$recipients = []
|
102
|
-
$content = nil
|
103
|
-
$delay = 60..300
|
104
|
-
|
105
|
-
opts = OptionParser.new do |opts|
|
106
|
-
opts.banner = "Usage: bulkmail <options>"
|
107
|
-
opts.define_head "Simple bulk-mailer."
|
108
|
-
opts.separator ""
|
109
|
-
opts.separator "Options:"
|
110
|
-
|
111
|
-
opts.on("-h", "--helo HOSTNAME", "HELO host name.") do |v|
|
112
|
-
$helo = v
|
113
|
-
end
|
114
|
-
|
115
|
-
opts.on("-r", "--recipients filename", "Recipients file name") do |v|
|
116
|
-
$recipients = IO.readlines(v).map {|l| l =~ /(.*)(\r\n|\n)$/ ? $1 : l}.compact
|
117
|
-
end
|
118
|
-
|
119
|
-
opts.on("-c", "--content filename", "Content file name") do |v|
|
120
|
-
$content = IO.read(v)
|
121
|
-
end
|
122
|
-
|
123
|
-
opts.on("-f", "--from from", "From address") do |v|
|
124
|
-
$from = v
|
125
|
-
end
|
126
|
-
|
127
|
-
opts.on('-n', "--nodelay", "No delay") do |v|
|
128
|
-
$delay = 0
|
129
|
-
end
|
130
|
-
|
131
|
-
# No argument, shows at tail. This will print an options summary.
|
132
|
-
# Try it and see!
|
133
|
-
opts.on_tail("-?", "--help", "Show this message") do
|
134
|
-
puts opts
|
135
|
-
exit
|
136
|
-
end
|
137
|
-
|
138
|
-
# Another typical switch to print the version.
|
139
|
-
opts.on_tail("-v", "--version", "Show version") do
|
140
|
-
class << Gem; attr_accessor :loaded_specs; end
|
141
|
-
specs = Gem.loaded_specs['bulkmail']
|
142
|
-
puts "bulkmail #{specs.version} (#{specs.date.strftime '%Y-%m-%d'})"
|
143
|
-
exit
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
begin
|
148
|
-
opts.parse! ARGV
|
149
|
-
rescue => e
|
150
|
-
puts e.message
|
151
|
-
puts e.backtrace.first
|
152
|
-
exit
|
153
|
-
end
|
154
|
-
|
155
|
-
unless $content
|
156
|
-
puts opts
|
157
|
-
exit
|
158
|
-
end
|
159
|
-
|
160
|
-
trap('INT') {exit}
|
161
|
-
|
162
|
-
puts "Please hold on..."
|
163
|
-
|
164
|
-
sender = BulkMail::Sender.new({
|
165
|
-
:list => $recipients,
|
166
|
-
:from => $from,
|
167
|
-
:message => $content,
|
168
|
-
:helo => $helo,
|
169
|
-
:delay => $delay
|
170
|
-
})
|
171
|
-
sender.start
|