sequel 0.3.4.1 → 0.4.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 +24 -0
- data/README +2 -0
- data/Rakefile +2 -2
- data/lib/{sequel → sequel-core}/array_keys.rb +0 -0
- data/lib/{sequel → sequel-core}/connection_pool.rb +0 -0
- data/lib/{sequel → sequel-core}/core_ext.rb +0 -0
- data/lib/{sequel → sequel-core}/core_sql.rb +8 -0
- data/lib/{sequel → sequel-core}/database.rb +4 -2
- data/lib/{sequel → sequel-core}/dataset.rb +0 -0
- data/lib/{sequel → sequel-core}/dataset/convenience.rb +0 -0
- data/lib/{sequel → sequel-core}/dataset/sequelizer.rb +0 -0
- data/lib/{sequel → sequel-core}/dataset/sql.rb +22 -21
- data/lib/{sequel → sequel-core}/error.rb +0 -0
- data/lib/{sequel → sequel-core}/migration.rb +0 -0
- data/lib/{sequel → sequel-core}/model.rb +5 -0
- data/lib/{sequel → sequel-core}/model/base.rb +0 -0
- data/lib/{sequel → sequel-core}/model/caching.rb +0 -0
- data/lib/{sequel → sequel-core}/model/hooks.rb +0 -0
- data/lib/{sequel → sequel-core}/model/record.rb +0 -0
- data/lib/{sequel → sequel-core}/model/relations.rb +0 -0
- data/lib/{sequel → sequel-core}/model/schema.rb +0 -0
- data/lib/{sequel → sequel-core}/pretty_table.rb +0 -0
- data/lib/{sequel → sequel-core}/schema.rb +0 -0
- data/lib/{sequel → sequel-core}/schema/schema_generator.rb +0 -0
- data/lib/{sequel → sequel-core}/schema/schema_sql.rb +0 -0
- data/lib/{sequel → sequel-core}/worker.rb +23 -10
- data/lib/sequel.rb +3 -1
- data/lib/sequel/dbi.rb +33 -0
- data/lib/sequel/informix.rb +78 -0
- data/lib/sequel/mysql.rb +0 -2
- data/lib/sequel/postgres.rb +16 -0
- data/spec/adapters/mysql_spec.rb +11 -0
- data/spec/adapters/postgres_spec.rb +5 -0
- data/spec/dataset_spec.rb +26 -11
- data/spec/worker_spec.rb +35 -2
- metadata +97 -88
data/CHANGELOG
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
=== 0.4.0 (2007-11-24)
|
2
|
+
|
3
|
+
* Reorganized lib directory structure.
|
4
|
+
|
5
|
+
* Added support for dbi-xxx URI schemes (#86).
|
6
|
+
|
7
|
+
* Fixed problem in Database#uri where setting the password would raise an error (#87).
|
8
|
+
|
9
|
+
* Improved Dataset#insert_sql to correctly handle string keys (#92).
|
10
|
+
|
11
|
+
* Improved error-handling for worker threads. Errors are saved to an array and are accessible through #errors (#91).
|
12
|
+
|
13
|
+
* Dataset#uniq/distinct can now accept a column list for DISTINCT ON clauses.
|
14
|
+
|
15
|
+
* Fixed Model.all.
|
16
|
+
|
17
|
+
* Fixed literalization of strings with escape sequences in postgres adapter (#90).
|
18
|
+
|
19
|
+
* Added support for literalizing BigDecimal values (#89).
|
20
|
+
|
21
|
+
* Fixed column qualification for joined datasets (thanks Christian).
|
22
|
+
|
23
|
+
* Implemented experimental informix adapter.
|
24
|
+
|
1
25
|
=== 0.3.4.1 (2007-11-10)
|
2
26
|
|
3
27
|
* Changed Dataset#select_sql to support queries without a FROM clause.
|
data/README
CHANGED
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'fileutils'
|
|
6
6
|
include FileUtils
|
7
7
|
|
8
8
|
NAME = "sequel"
|
9
|
-
VERS = "0.
|
9
|
+
VERS = "0.4.0"
|
10
10
|
CLEAN.include ['**/.*.sw?', 'pkg/*', '.config', 'doc/*', 'coverage/*']
|
11
11
|
RDOC_OPTS = ['--quiet', '--title', "Sequel: Concise ORM for Ruby",
|
12
12
|
"--opname", "index.html",
|
@@ -25,7 +25,7 @@ Rake::RDocTask.new do |rdoc|
|
|
25
25
|
rdoc.options += RDOC_OPTS
|
26
26
|
rdoc.main = "README"
|
27
27
|
rdoc.title = "Sequel: Lightweight ORM library for Ruby"
|
28
|
-
rdoc.rdoc_files.add ['README', 'COPYING', 'lib/sequel.rb', 'lib
|
28
|
+
rdoc.rdoc_files.add ['README', 'COPYING', 'lib/sequel.rb', 'lib/**/*.rb']
|
29
29
|
end
|
30
30
|
|
31
31
|
spec = Gem::Specification.new do |s|
|
File without changes
|
File without changes
|
File without changes
|
@@ -68,6 +68,14 @@ module Sequel
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
class QualifiedColumnRef < Expression
|
72
|
+
def initialize(t, c); @t, @c = t, c; end
|
73
|
+
|
74
|
+
def to_s(ds)
|
75
|
+
"#{@t}.#{ds.literal(@c)}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
71
79
|
class Function < Expression
|
72
80
|
def initialize(f, *args); @f, @args = f, args; end
|
73
81
|
|
@@ -64,7 +64,7 @@ module Sequel
|
|
64
64
|
nil
|
65
65
|
)
|
66
66
|
uri.user = @opts[:user]
|
67
|
-
uri.password = @opts[:password]
|
67
|
+
uri.password = @opts[:password] if uri.user
|
68
68
|
uri.to_s
|
69
69
|
end
|
70
70
|
alias url uri # Because I don't care much for the semantic difference.
|
@@ -285,7 +285,9 @@ module Sequel
|
|
285
285
|
# DB = Sequel.open 'sqlite:///blog.db'
|
286
286
|
def self.connect(conn_string, more_opts = nil)
|
287
287
|
uri = URI.parse(conn_string)
|
288
|
-
|
288
|
+
scheme = uri.scheme
|
289
|
+
scheme = :dbi if scheme =~ /^dbi-(.+)/
|
290
|
+
c = @@adapters[scheme.to_sym]
|
289
291
|
raise SequelError, "Invalid database scheme" unless c
|
290
292
|
c.new(c.uri_to_options(uri).merge(more_opts || {}))
|
291
293
|
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -14,16 +14,15 @@ module Sequel
|
|
14
14
|
# Returns a qualified column name (including a table name) if the column
|
15
15
|
# name isn't already qualified.
|
16
16
|
def qualified_column_name(column, table)
|
17
|
-
|
18
|
-
if
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# check if the table is aliased
|
23
|
-
if table =~ ALIASED_REGEXP
|
17
|
+
s = literal(column)
|
18
|
+
if s =~ QUALIFIED_REGEXP
|
19
|
+
return column
|
20
|
+
else
|
21
|
+
if (table =~ ALIASED_REGEXP)
|
24
22
|
table = $2
|
25
23
|
end
|
26
|
-
|
24
|
+
Sequel::SQL::QualifiedColumnRef.new(table, column)
|
25
|
+
# "#{table}.#{column}"
|
27
26
|
end
|
28
27
|
end
|
29
28
|
|
@@ -86,6 +85,7 @@ module Sequel
|
|
86
85
|
when LiteralString: v
|
87
86
|
when String: "'#{v.gsub(/'/, "''")}'"
|
88
87
|
when Integer, Float: v.to_s
|
88
|
+
when BigDecimal: v.to_s("F")
|
89
89
|
when NilClass: NULL
|
90
90
|
when TrueClass: TRUE
|
91
91
|
when FalseClass: FALSE
|
@@ -109,10 +109,7 @@ module Sequel
|
|
109
109
|
case expr
|
110
110
|
when Hash:
|
111
111
|
parenthesize = false if expr.size == 1
|
112
|
-
|
113
|
-
# N.B.: We convert this to an array and sort it in order to have a fixed order for testability.
|
114
|
-
# Hash in Ruby 1.8 has no order, so Hash#map is indeterminate, which makes it hard to test.
|
115
|
-
fmt = expr.to_a.sort_by { |k, v| k.to_s }.map {|i| compare_expr(i[0], i[1])}.join(AND_SEPARATOR)
|
112
|
+
fmt = expr.map {|i| compare_expr(i[0], i[1])}.join(AND_SEPARATOR)
|
116
113
|
when Array:
|
117
114
|
fmt = expr.shift.gsub(QUESTION_MARK) {literal(expr.shift)}
|
118
115
|
when Proc:
|
@@ -137,10 +134,10 @@ module Sequel
|
|
137
134
|
end
|
138
135
|
|
139
136
|
# Returns a copy of the dataset with the distinct option.
|
140
|
-
def uniq
|
141
|
-
clone_merge(:distinct =>
|
137
|
+
def uniq(*args)
|
138
|
+
clone_merge(:distinct => args)
|
142
139
|
end
|
143
|
-
|
140
|
+
alias_method :distinct, :uniq
|
144
141
|
|
145
142
|
# Returns a copy of the dataset with the order changed.
|
146
143
|
def order(*order)
|
@@ -320,8 +317,8 @@ module Sequel
|
|
320
317
|
|
321
318
|
join_conditions = {}
|
322
319
|
expr.each do |k, v|
|
323
|
-
k = qualified_column_name(k, table)
|
324
|
-
v = qualified_column_name(v, @opts[:last_joined_table] || @opts[:from].first)
|
320
|
+
k = qualified_column_name(k, table) if k.is_a?(Symbol)
|
321
|
+
v = qualified_column_name(v, @opts[:last_joined_table] || @opts[:from].first) if v.is_a?(Symbol)
|
325
322
|
join_conditions[k] = v
|
326
323
|
end
|
327
324
|
" #{join_type} #{table} ON #{expression_list(join_conditions)}"
|
@@ -371,9 +368,13 @@ module Sequel
|
|
371
368
|
|
372
369
|
columns = opts[:select]
|
373
370
|
select_columns = columns ? column_list(columns) : WILDCARD
|
374
|
-
|
375
|
-
|
376
|
-
|
371
|
+
|
372
|
+
if distinct = opts[:distinct]
|
373
|
+
distinct_clause = distinct.empty? ? "DISTINCT" : "DISTINCT ON (#{column_list(distinct)})"
|
374
|
+
sql = "SELECT #{distinct_clause} #{select_columns}"
|
375
|
+
else
|
376
|
+
sql = "SELECT #{select_columns}"
|
377
|
+
end
|
377
378
|
|
378
379
|
if opts[:from]
|
379
380
|
sql << " FROM #{source_list(opts[:from])}"
|
@@ -453,7 +454,7 @@ module Sequel
|
|
453
454
|
"INSERT INTO #{@opts[:from]} DEFAULT VALUES"
|
454
455
|
else
|
455
456
|
fl, vl = [], []
|
456
|
-
values.each {|k, v| fl <<
|
457
|
+
values.each {|k, v| fl << k.to_s; vl << literal(v)}
|
457
458
|
"INSERT INTO #{@opts[:from]} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
|
458
459
|
end
|
459
460
|
when Dataset
|
File without changes
|
File without changes
|
@@ -305,6 +305,11 @@ module Sequel
|
|
305
305
|
table_name = dataset.opts[:from].first
|
306
306
|
dataset.join(*args).select(table_name.to_sym.ALL)
|
307
307
|
end
|
308
|
+
|
309
|
+
# Returns an array containing all model records
|
310
|
+
def self.all
|
311
|
+
dataset.all
|
312
|
+
end
|
308
313
|
|
309
314
|
# Returns value of attribute.
|
310
315
|
def [](column)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -5,22 +5,22 @@ module Sequel
|
|
5
5
|
class WorkerStopError < RuntimeError; end
|
6
6
|
|
7
7
|
attr_reader :queue
|
8
|
+
attr_reader :errors
|
8
9
|
|
9
10
|
def initialize(db = nil)
|
10
11
|
@queue = Queue.new
|
12
|
+
@errors = []
|
11
13
|
t = self
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
super {t.work}
|
16
|
-
end
|
14
|
+
t.abort_on_exception = true
|
15
|
+
@transaction = !db.nil?
|
16
|
+
db ? super {db.transaction {t.work}} : super {t.work}
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def work
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
loop {next_job}
|
21
|
+
rescue WorkerStopError # signals the worker thread to stop
|
22
|
+
ensure
|
23
|
+
rollback! if @transaction && !@errors.empty?
|
24
24
|
end
|
25
25
|
|
26
26
|
def busy?
|
@@ -29,6 +29,7 @@ module Sequel
|
|
29
29
|
|
30
30
|
def async(proc = nil, &block)
|
31
31
|
@queue << (proc || block)
|
32
|
+
self
|
32
33
|
end
|
33
34
|
alias_method :add, :async
|
34
35
|
alias_method :<<, :async
|
@@ -40,5 +41,17 @@ module Sequel
|
|
40
41
|
self.raise WorkerStopError
|
41
42
|
super
|
42
43
|
end
|
44
|
+
|
45
|
+
private
|
46
|
+
def next_job
|
47
|
+
@cur = @queue.pop
|
48
|
+
@cur.call
|
49
|
+
rescue WorkerStopError => e
|
50
|
+
raise e
|
51
|
+
rescue Exception => e
|
52
|
+
@errors << e
|
53
|
+
ensure
|
54
|
+
@cur = nil
|
55
|
+
end
|
43
56
|
end
|
44
57
|
end
|
data/lib/sequel.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'metaid'
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'bigdecimal/util'
|
2
4
|
|
3
5
|
files = %w[
|
4
6
|
core_ext core_sql array_keys error connection_pool pretty_table
|
5
7
|
dataset migration model schema database worker
|
6
8
|
]
|
7
|
-
dir = File.join(File.dirname(__FILE__), 'sequel')
|
9
|
+
dir = File.join(File.dirname(__FILE__), 'sequel-core')
|
8
10
|
files.each {|f| require(File.join(dir, f))}
|
9
11
|
|
10
12
|
module Sequel #:nodoc:
|
data/lib/sequel/dbi.rb
CHANGED
@@ -8,6 +8,39 @@ module Sequel
|
|
8
8
|
module DBI
|
9
9
|
class Database < Sequel::Database
|
10
10
|
set_adapter_scheme :dbi
|
11
|
+
|
12
|
+
DBI_ADAPTERS = {
|
13
|
+
:ado => "ADO",
|
14
|
+
:db2 => "DB2",
|
15
|
+
:frontbase => "FrontBase",
|
16
|
+
:interbase => "InterBase",
|
17
|
+
:msql => "Msql",
|
18
|
+
:mysql => "Mysql",
|
19
|
+
:odbc => "ODBC",
|
20
|
+
:oracle => "Oracle",
|
21
|
+
:pg => "Pg",
|
22
|
+
:proxy => "Proxy",
|
23
|
+
:sqlite => "SQLite",
|
24
|
+
:sqlrelay => "SQLRelay"
|
25
|
+
}
|
26
|
+
|
27
|
+
# Converts a uri to an options hash. These options are then passed
|
28
|
+
# to a newly created database object.
|
29
|
+
def self.uri_to_options(uri)
|
30
|
+
database = (uri.path =~ /\/(.*)/) && ($1)
|
31
|
+
if uri.scheme =~ /dbi-(.+)/
|
32
|
+
adapter = DBI_ADAPTERS[$1.to_sym] || $1
|
33
|
+
database = "#{adapter}:#{database}"
|
34
|
+
end
|
35
|
+
{
|
36
|
+
:user => uri.user,
|
37
|
+
:password => uri.password,
|
38
|
+
:host => uri.host,
|
39
|
+
:port => uri.port,
|
40
|
+
:database => database
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
11
44
|
|
12
45
|
def connect
|
13
46
|
dbname = @opts[:database]
|
@@ -0,0 +1,78 @@
|
|
1
|
+
if !Object.const_defined?('Sequel')
|
2
|
+
require File.join(File.dirname(__FILE__), '../sequel')
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'informix'
|
6
|
+
|
7
|
+
module Sequel
|
8
|
+
module Informix
|
9
|
+
class Database < Sequel::Database
|
10
|
+
set_adapter_scheme :informix
|
11
|
+
|
12
|
+
# AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
|
13
|
+
#
|
14
|
+
# def auto_increment_sql
|
15
|
+
# AUTO_INCREMENT
|
16
|
+
# end
|
17
|
+
|
18
|
+
def connect
|
19
|
+
::Informix.connect(@opts[:database], @opts[:user], @opts[:password])
|
20
|
+
end
|
21
|
+
|
22
|
+
def disconnect
|
23
|
+
@pool.disconnect {|c| c.close}
|
24
|
+
end
|
25
|
+
|
26
|
+
def dataset(opts = nil)
|
27
|
+
Sequel::Informix::Dataset.new(self, opts)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns number of rows affected
|
31
|
+
def execute(sql)
|
32
|
+
@logger.info(sql) if @logger
|
33
|
+
@pool.hold {|c| c.do(sql)}
|
34
|
+
end
|
35
|
+
alias_method :do, :execute
|
36
|
+
|
37
|
+
def query(sql, &block)
|
38
|
+
@logger.info(sql) if @logger
|
39
|
+
@pool.hold {|c| block[c.cursor(sql)]}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Dataset < Sequel::Dataset
|
44
|
+
def literal(v)
|
45
|
+
case v
|
46
|
+
when Time: literal(v.iso8601)
|
47
|
+
else
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def fetch_rows(sql, &block)
|
53
|
+
@db.synchronize do
|
54
|
+
@db.query(sql) do |cursor|
|
55
|
+
begin
|
56
|
+
cursor.open.each_hash {|r| block[r]}
|
57
|
+
ensure
|
58
|
+
cursor.drop
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def insert(*values)
|
66
|
+
@db.do insert_sql(*values)
|
67
|
+
end
|
68
|
+
|
69
|
+
def update(values, opts = nil)
|
70
|
+
@db.do update_sql(values, opts)
|
71
|
+
end
|
72
|
+
|
73
|
+
def delete(opts = nil)
|
74
|
+
@db.do delete_sql(opts)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/sequel/mysql.rb
CHANGED
data/lib/sequel/postgres.rb
CHANGED
@@ -18,6 +18,22 @@ class PGconn
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
class << self
|
22
|
+
# The postgres gem's string quoting doesn't render string literals properly, which this fixes.
|
23
|
+
#
|
24
|
+
# "a basic string" #=> 'a basic string'
|
25
|
+
# "this\or that" #=> E'this\\or that'
|
26
|
+
#
|
27
|
+
# See <http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html> for details.
|
28
|
+
def quote_with_proper_escaping(s)
|
29
|
+
value = quote_without_proper_escaping(s)
|
30
|
+
value = "E#{value}" if value =~ /\\/
|
31
|
+
return value
|
32
|
+
end
|
33
|
+
alias_method :quote_without_proper_escaping, :quote
|
34
|
+
alias_method :quote, :quote_with_proper_escaping
|
35
|
+
end
|
36
|
+
|
21
37
|
def connected?
|
22
38
|
status == PGconn::CONNECTION_OK
|
23
39
|
end
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -234,3 +234,14 @@ context "Simple stored procedure test" do
|
|
234
234
|
@server_id_by_sp.should == @server_id # compare it to output from stored procedure
|
235
235
|
end
|
236
236
|
end
|
237
|
+
|
238
|
+
context "Joiמed MySQL dataset" do
|
239
|
+
setup do
|
240
|
+
@ds = MYSQL_DB[:nodes].join(:attributes, :node_id => :id)
|
241
|
+
end
|
242
|
+
|
243
|
+
specify "should quote fields correctly" do
|
244
|
+
@ds.sql.should == \
|
245
|
+
"SELECT * FROM nodes INNER JOIN attributes ON (attributes.`node_id` = nodes.`id`)"
|
246
|
+
end
|
247
|
+
end
|
@@ -92,6 +92,11 @@ context "A PostgreSQL dataset" do
|
|
92
92
|
@d.filter(:name => /bc/).count.should == 2
|
93
93
|
@d.filter(:name => /^bc/).count.should == 1
|
94
94
|
end
|
95
|
+
|
96
|
+
specify "should consider strings containing backslashes to be escaped string literals" do
|
97
|
+
PGconn.quote("\\dingo").should == "E'\\\\dingo'" # literally, E'\\dingo'
|
98
|
+
PGconn.quote("dingo").should == "'dingo'"
|
99
|
+
end
|
95
100
|
end
|
96
101
|
|
97
102
|
context "A PostgreSQL dataset in array tuples mode" do
|
data/spec/dataset_spec.rb
CHANGED
@@ -119,6 +119,11 @@ context "A simple dataset" do
|
|
119
119
|
@dataset.insert_sql(v).should == "INSERT INTO test DEFAULT VALUES"
|
120
120
|
end
|
121
121
|
|
122
|
+
specify "should format an insert statement with string keys" do
|
123
|
+
@dataset.insert_sql('name' => 'wxyz', 'price' => 342).
|
124
|
+
should match(/INSERT INTO test \(name, price\) VALUES \('wxyz', 342\)|INSERT INTO test \(price, name\) VALUES \(342, 'wxyz'\)/)
|
125
|
+
end
|
126
|
+
|
122
127
|
specify "should format an insert statement with a model instance" do
|
123
128
|
dbb = Sequel::Database.new
|
124
129
|
|
@@ -573,6 +578,10 @@ context "Dataset#literal" do
|
|
573
578
|
@dataset.update_sql(:a => 'a + 2'.expr).should ==
|
574
579
|
'UPDATE test SET a = a + 2'
|
575
580
|
end
|
581
|
+
|
582
|
+
specify "should literalize BigDecimal instances correctly" do
|
583
|
+
@dataset.literal(BigDecimal.new("80")).should == "80.0"
|
584
|
+
end
|
576
585
|
end
|
577
586
|
|
578
587
|
context "Dataset#from" do
|
@@ -796,12 +805,12 @@ context "Dataset#qualified_column_name" do
|
|
796
805
|
|
797
806
|
specify "should return the same if already qualified" do
|
798
807
|
@dataset.qualified_column_name('test.a'.lit, :items).should == 'test.a'
|
799
|
-
@dataset.qualified_column_name(:ccc__b, :items).should ==
|
808
|
+
@dataset.qualified_column_name(:ccc__b, :items).should == :ccc__b
|
800
809
|
end
|
801
810
|
|
802
811
|
specify "should qualify the column with the supplied table name" do
|
803
|
-
@dataset.qualified_column_name('a'.lit, :items).should == 'items.a'
|
804
|
-
@dataset.qualified_column_name(:b1, :items).should == 'items.b1'
|
812
|
+
@dataset.qualified_column_name('a'.lit, :items).to_s(@dataset).should == 'items.a'
|
813
|
+
@dataset.qualified_column_name(:b1, :items).to_s(@dataset).should == 'items.b1'
|
805
814
|
end
|
806
815
|
end
|
807
816
|
|
@@ -857,6 +866,12 @@ context "Dataset#uniq" do
|
|
857
866
|
specify "should be aliased by Dataset#distinct" do
|
858
867
|
@dataset.distinct.sql.should == 'SELECT DISTINCT name FROM test'
|
859
868
|
end
|
869
|
+
|
870
|
+
specify "should accept an expression list" do
|
871
|
+
@dataset.uniq(:a, :b).sql.should == 'SELECT DISTINCT ON (a, b) name FROM test'
|
872
|
+
|
873
|
+
@dataset.uniq(:stamp.cast_as(:integer), :node_id).sql.should == 'SELECT DISTINCT ON (cast(stamp AS integer), node_id) name FROM test'
|
874
|
+
end
|
860
875
|
end
|
861
876
|
|
862
877
|
context "Dataset#count" do
|
@@ -1013,14 +1028,14 @@ context "Dataset#join_table" do
|
|
1013
1028
|
end
|
1014
1029
|
|
1015
1030
|
specify "should allow for arbitrary conditions in the JOIN clause" do
|
1016
|
-
@d.join_table(:left_outer, :categories, :
|
1017
|
-
'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.
|
1018
|
-
@d.join_table(:left_outer, :categories, :
|
1019
|
-
"SELECT * FROM items LEFT OUTER JOIN categories ON (categories.categorizable_type = 'Post')
|
1020
|
-
@d.join_table(:left_outer, :categories, :
|
1021
|
-
"SELECT * FROM items LEFT OUTER JOIN categories ON (categories.
|
1022
|
-
@d.join_table(:left_outer, :categories, :
|
1023
|
-
"SELECT * FROM items LEFT OUTER JOIN categories ON (categories.
|
1031
|
+
@d.join_table(:left_outer, :categories, :status => 0).sql.should ==
|
1032
|
+
'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.status = 0)'
|
1033
|
+
@d.join_table(:left_outer, :categories, :categorizable_type => "Post").sql.should ==
|
1034
|
+
"SELECT * FROM items LEFT OUTER JOIN categories ON (categories.categorizable_type = 'Post')"
|
1035
|
+
@d.join_table(:left_outer, :categories, :timestamp => "CURRENT_TIMESTAMP".lit).sql.should ==
|
1036
|
+
"SELECT * FROM items LEFT OUTER JOIN categories ON (categories.timestamp = CURRENT_TIMESTAMP)"
|
1037
|
+
@d.join_table(:left_outer, :categories, :status => [1, 2, 3]).sql.should ==
|
1038
|
+
"SELECT * FROM items LEFT OUTER JOIN categories ON (categories.status IN (1, 2, 3))"
|
1024
1039
|
end
|
1025
1040
|
end
|
1026
1041
|
|
data/spec/worker_spec.rb
CHANGED
@@ -32,7 +32,19 @@ context "A worker" do
|
|
32
32
|
|
33
33
|
@w.join
|
34
34
|
values.should == [1, 2, 3]
|
35
|
-
|
35
|
+
end
|
36
|
+
|
37
|
+
specify "should isolate errors and hold them in #errors" do
|
38
|
+
values = []
|
39
|
+
@w.add {values << 1}
|
40
|
+
@w.async {values << 2}
|
41
|
+
@w.async {raise "bad bad bad"}
|
42
|
+
@w << proc {values << 3}
|
43
|
+
|
44
|
+
@w.join
|
45
|
+
values.should == [1, 2, 3]
|
46
|
+
@w.errors.size.should == 1
|
47
|
+
@w.errors.first.message.should == 'bad bad bad'
|
36
48
|
end
|
37
49
|
end
|
38
50
|
|
@@ -40,7 +52,13 @@ context "A worker with a given db" do
|
|
40
52
|
setup do
|
41
53
|
@db = MockDatabase.new
|
42
54
|
@m = Module.new do
|
43
|
-
def transaction
|
55
|
+
def transaction
|
56
|
+
execute('BEGIN')
|
57
|
+
yield
|
58
|
+
execute('COMMIT')
|
59
|
+
rescue
|
60
|
+
execute('ROLLBACK')
|
61
|
+
end
|
44
62
|
end
|
45
63
|
@db.extend(@m)
|
46
64
|
@w = Sequel::Worker.new(@db)
|
@@ -60,4 +78,19 @@ context "A worker with a given db" do
|
|
60
78
|
'COMMIT'
|
61
79
|
]
|
62
80
|
end
|
81
|
+
|
82
|
+
specify "should rollback the transaction if any error is raised" do
|
83
|
+
@w.async {@db[:items] << {:x => 1}}
|
84
|
+
@w.async {sleep 0.2; raise "that's bad"}
|
85
|
+
@w.async {@db[:items] << {:x => 2}}
|
86
|
+
@w.join
|
87
|
+
@db.sqls.should == [
|
88
|
+
'BEGIN',
|
89
|
+
'INSERT INTO items (x) VALUES (1)',
|
90
|
+
'INSERT INTO items (x) VALUES (2)',
|
91
|
+
'ROLLBACK'
|
92
|
+
]
|
93
|
+
@w.errors.size.should == 1
|
94
|
+
@w.errors.first.message.should == "that's bad"
|
95
|
+
end
|
63
96
|
end
|
metadata
CHANGED
@@ -1,33 +1,54 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.4
|
3
|
-
specification_version: 1
|
4
2
|
name: sequel
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-11-10 00:00:00 +02:00
|
8
|
-
summary: Lightweight ORM library for Ruby
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: ciconia@gmail.com
|
12
|
-
homepage: http://sequel.rubyforge.org
|
13
|
-
rubyforge_project:
|
14
|
-
description: Lightweight ORM library for Ruby
|
15
|
-
autorequire:
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: true
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">="
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 1.8.4
|
24
|
-
version:
|
4
|
+
version: 0.4.0
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors:
|
30
7
|
- Sharon Rosner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2007-11-24 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: metaid
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: ParseTree
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 2.0.0
|
32
|
+
version:
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: ruby2ruby
|
35
|
+
version_requirement:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: "0"
|
41
|
+
version:
|
42
|
+
description: Lightweight ORM library for Ruby
|
43
|
+
email: ciconia@gmail.com
|
44
|
+
executables:
|
45
|
+
- sequel
|
46
|
+
extensions: []
|
47
|
+
|
48
|
+
extra_rdoc_files:
|
49
|
+
- README
|
50
|
+
- CHANGELOG
|
51
|
+
- COPYING
|
31
52
|
files:
|
32
53
|
- COPYING
|
33
54
|
- README
|
@@ -54,43 +75,46 @@ files:
|
|
54
75
|
- spec/worker_spec.rb
|
55
76
|
- lib/sequel
|
56
77
|
- lib/sequel/ado.rb
|
57
|
-
- lib/sequel/array_keys.rb
|
58
|
-
- lib/sequel/connection_pool.rb
|
59
|
-
- lib/sequel/core_ext.rb
|
60
|
-
- lib/sequel/core_sql.rb
|
61
|
-
- lib/sequel/database.rb
|
62
|
-
- lib/sequel/dataset
|
63
|
-
- lib/sequel/dataset/convenience.rb
|
64
|
-
- lib/sequel/dataset/sequelizer.rb
|
65
|
-
- lib/sequel/dataset/sql.rb
|
66
|
-
- lib/sequel/dataset.rb
|
67
78
|
- lib/sequel/db2.rb
|
68
79
|
- lib/sequel/dbi.rb
|
69
|
-
- lib/sequel/
|
70
|
-
- lib/sequel/migration.rb
|
71
|
-
- lib/sequel/model
|
72
|
-
- lib/sequel/model/base.rb
|
73
|
-
- lib/sequel/model/caching.rb
|
74
|
-
- lib/sequel/model/hooks.rb
|
75
|
-
- lib/sequel/model/record.rb
|
76
|
-
- lib/sequel/model/relations.rb
|
77
|
-
- lib/sequel/model/schema.rb
|
78
|
-
- lib/sequel/model.rb
|
80
|
+
- lib/sequel/informix.rb
|
79
81
|
- lib/sequel/mysql.rb
|
80
82
|
- lib/sequel/odbc.rb
|
81
83
|
- lib/sequel/oracle.rb
|
82
84
|
- lib/sequel/postgres.rb
|
83
|
-
- lib/sequel/pretty_table.rb
|
84
|
-
- lib/sequel/schema
|
85
|
-
- lib/sequel/schema/schema_generator.rb
|
86
|
-
- lib/sequel/schema/schema_sql.rb
|
87
|
-
- lib/sequel/schema.rb
|
88
85
|
- lib/sequel/sqlite.rb
|
89
|
-
- lib/sequel
|
86
|
+
- lib/sequel-core
|
87
|
+
- lib/sequel-core/array_keys.rb
|
88
|
+
- lib/sequel-core/connection_pool.rb
|
89
|
+
- lib/sequel-core/core_ext.rb
|
90
|
+
- lib/sequel-core/core_sql.rb
|
91
|
+
- lib/sequel-core/database.rb
|
92
|
+
- lib/sequel-core/dataset
|
93
|
+
- lib/sequel-core/dataset/convenience.rb
|
94
|
+
- lib/sequel-core/dataset/sequelizer.rb
|
95
|
+
- lib/sequel-core/dataset/sql.rb
|
96
|
+
- lib/sequel-core/dataset.rb
|
97
|
+
- lib/sequel-core/error.rb
|
98
|
+
- lib/sequel-core/migration.rb
|
99
|
+
- lib/sequel-core/model
|
100
|
+
- lib/sequel-core/model/base.rb
|
101
|
+
- lib/sequel-core/model/caching.rb
|
102
|
+
- lib/sequel-core/model/hooks.rb
|
103
|
+
- lib/sequel-core/model/record.rb
|
104
|
+
- lib/sequel-core/model/relations.rb
|
105
|
+
- lib/sequel-core/model/schema.rb
|
106
|
+
- lib/sequel-core/model.rb
|
107
|
+
- lib/sequel-core/pretty_table.rb
|
108
|
+
- lib/sequel-core/schema
|
109
|
+
- lib/sequel-core/schema/schema_generator.rb
|
110
|
+
- lib/sequel-core/schema/schema_sql.rb
|
111
|
+
- lib/sequel-core/schema.rb
|
112
|
+
- lib/sequel-core/worker.rb
|
90
113
|
- lib/sequel.rb
|
91
114
|
- CHANGELOG
|
92
|
-
|
93
|
-
|
115
|
+
has_rdoc: true
|
116
|
+
homepage: http://sequel.rubyforge.org
|
117
|
+
post_install_message:
|
94
118
|
rdoc_options:
|
95
119
|
- --quiet
|
96
120
|
- --title
|
@@ -105,41 +129,26 @@ rdoc_options:
|
|
105
129
|
- ^(examples|extras)\/
|
106
130
|
- --exclude
|
107
131
|
- lib/sequel.rb
|
108
|
-
|
109
|
-
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
-
|
114
|
-
|
115
|
-
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.8.4
|
139
|
+
version:
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: "0"
|
145
|
+
version:
|
116
146
|
requirements: []
|
117
147
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
- !ruby/object:Gem::Version
|
126
|
-
version: 0.0.0
|
127
|
-
version:
|
128
|
-
- !ruby/object:Gem::Dependency
|
129
|
-
name: ParseTree
|
130
|
-
version_requirement:
|
131
|
-
version_requirements: !ruby/object:Gem::Version::Requirement
|
132
|
-
requirements:
|
133
|
-
- - ">="
|
134
|
-
- !ruby/object:Gem::Version
|
135
|
-
version: 2.0.0
|
136
|
-
version:
|
137
|
-
- !ruby/object:Gem::Dependency
|
138
|
-
name: ruby2ruby
|
139
|
-
version_requirement:
|
140
|
-
version_requirements: !ruby/object:Gem::Version::Requirement
|
141
|
-
requirements:
|
142
|
-
- - ">"
|
143
|
-
- !ruby/object:Gem::Version
|
144
|
-
version: 0.0.0
|
145
|
-
version:
|
148
|
+
rubyforge_project:
|
149
|
+
rubygems_version: 0.9.5
|
150
|
+
signing_key:
|
151
|
+
specification_version: 2
|
152
|
+
summary: Lightweight ORM library for Ruby
|
153
|
+
test_files: []
|
154
|
+
|