sequel_core 1.5.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|