sequel 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +16 -0
- data/Rakefile +1 -1
- data/lib/sequel.rb +1 -1
- data/lib/sequel/array_keys.rb +2 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core_ext.rb +53 -12
- data/lib/sequel/database.rb +1 -1
- data/lib/sequel/dataset/sql.rb +11 -11
- data/lib/sequel/mysql.rb +9 -9
- data/lib/sequel/postgres.rb +2 -2
- data/lib/sequel/schema/schema_sql.rb +4 -4
- data/lib/sequel/sqlite.rb +3 -3
- data/lib/sequel/worker.rb +44 -0
- data/spec/adapters/mysql_spec.rb +1 -1
- data/spec/adapters/oracle_spec.rb +130 -0
- data/spec/array_keys_spec.rb +6 -6
- data/spec/connection_pool_spec.rb +1 -1
- data/spec/core_ext_spec.rb +59 -1
- data/spec/database_spec.rb +17 -13
- data/spec/dataset_spec.rb +32 -32
- data/spec/model_spec.rb +14 -14
- data/spec/schema_spec.rb +26 -26
- data/spec/worker_spec.rb +63 -0
- metadata +5 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
=== 0.3.3 (2007-11-04)
|
2
|
+
|
3
|
+
* Revised code to generate SQL statements without trailing semicolons.
|
4
|
+
|
5
|
+
* Added Sequel::Worker implementation of a simple worker thread for asynchronous execution.
|
6
|
+
|
7
|
+
* Added spec for Oracle adapter.
|
8
|
+
|
9
|
+
* Fixed Oracle adapter to format INSERT statements without semicolons (thanks Liming Lian).
|
10
|
+
|
11
|
+
* Renamed alias to Array#keys as Array#columns instead of Array#fields.
|
12
|
+
|
13
|
+
* Renamed FieldCompositionMethods as ColumnCompositionMethods.
|
14
|
+
|
15
|
+
* Implemented Sequel::NumericExtensions to provide stuff like 30.days.ago.
|
16
|
+
|
1
17
|
=== 0.3.2 (2007-11-01)
|
2
18
|
|
3
19
|
* Added #to_column_name as alias to #to_field_name, #column_title as alias to #field_title.
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'fileutils'
|
|
6
6
|
include FileUtils
|
7
7
|
|
8
8
|
NAME = "sequel"
|
9
|
-
VERS = "0.3.
|
9
|
+
VERS = "0.3.3"
|
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",
|
data/lib/sequel.rb
CHANGED
@@ -2,7 +2,7 @@ require 'metaid'
|
|
2
2
|
|
3
3
|
files = %w[
|
4
4
|
core_ext array_keys error connection_pool pretty_table
|
5
|
-
dataset migration model schema database
|
5
|
+
dataset migration model schema database worker
|
6
6
|
]
|
7
7
|
dir = File.join(File.dirname(__FILE__), 'sequel')
|
8
8
|
files.each {|f| require(File.join(dir, f))}
|
data/lib/sequel/array_keys.rb
CHANGED
@@ -183,8 +183,8 @@ module ArrayKeys
|
|
183
183
|
end
|
184
184
|
end
|
185
185
|
|
186
|
-
alias_method :
|
187
|
-
alias_method :
|
186
|
+
alias_method :columns, :keys
|
187
|
+
alias_method :columns=, :keys=
|
188
188
|
end
|
189
189
|
|
190
190
|
# The DatasetExtensions module provides extensions that modify
|
@@ -43,7 +43,7 @@ module Sequel
|
|
43
43
|
# Assigns a connection to the current thread, yielding the connection
|
44
44
|
# to the supplied block.
|
45
45
|
#
|
46
|
-
# pool.hold {|conn| conn.execute('DROP TABLE posts
|
46
|
+
# pool.hold {|conn| conn.execute('DROP TABLE posts')}
|
47
47
|
#
|
48
48
|
# Pool#hold is re-entrant, meaning it can be called recursively in
|
49
49
|
# the same thread without blocking.
|
data/lib/sequel/core_ext.rb
CHANGED
@@ -17,6 +17,14 @@ class Array
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
# Range extensions
|
21
|
+
class Range
|
22
|
+
# Returns the interval between the beginning and end of the range.
|
23
|
+
def interval
|
24
|
+
last - first
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
20
28
|
module Sequel
|
21
29
|
# LiteralString is used to represent literal SQL expressions. An
|
22
30
|
# LiteralString is copied verbatim into an SQL statement. Instances of
|
@@ -68,7 +76,7 @@ end
|
|
68
76
|
|
69
77
|
# Methods to format column names and associated constructs. This module is
|
70
78
|
# included in String and Symbol.
|
71
|
-
module
|
79
|
+
module ColumnCompositionMethods
|
72
80
|
# Constructs a DESC clause for use in an ORDER BY clause.
|
73
81
|
def DESC
|
74
82
|
"#{to_column_name} DESC".lit
|
@@ -84,14 +92,14 @@ module FieldCompositionMethods
|
|
84
92
|
"#{to_s}.*".lit
|
85
93
|
end
|
86
94
|
|
87
|
-
|
88
|
-
|
95
|
+
COLUMN_TITLE_RE1 = /^(.*)\sAS\s(.+)$/i.freeze
|
96
|
+
COLUMN_TITLE_RE2 = /^([^\.]+)\.([^\.]+)$/.freeze
|
89
97
|
|
90
98
|
# Returns the column name. If the column name is aliased, the alias is
|
91
99
|
# returned.
|
92
100
|
def field_title
|
93
101
|
case s = to_column_name
|
94
|
-
when
|
102
|
+
when COLUMN_TITLE_RE1, COLUMN_TITLE_RE2: $2
|
95
103
|
else
|
96
104
|
s
|
97
105
|
end
|
@@ -101,17 +109,17 @@ end
|
|
101
109
|
|
102
110
|
# String extensions
|
103
111
|
class String
|
104
|
-
include
|
112
|
+
include ColumnCompositionMethods
|
105
113
|
end
|
106
114
|
|
107
115
|
# Symbol extensions
|
108
116
|
class Symbol
|
109
|
-
include
|
117
|
+
include ColumnCompositionMethods
|
110
118
|
|
111
119
|
|
112
|
-
|
113
|
-
|
114
|
-
|
120
|
+
COLUMN_REF_RE1 = /^(\w+)__(\w+)___(\w+)/.freeze
|
121
|
+
COLUMN_REF_RE2 = /^(\w+)___(\w+)$/.freeze
|
122
|
+
COLUMN_REF_RE3 = /^(\w+)__(\w+)$/.freeze
|
115
123
|
|
116
124
|
# Converts a symbol into a column name. This method supports underscore
|
117
125
|
# notation in order to express qualified (two underscores) and aliased
|
@@ -125,9 +133,9 @@ class Symbol
|
|
125
133
|
def to_field_name
|
126
134
|
s = to_s
|
127
135
|
case s
|
128
|
-
when
|
129
|
-
when
|
130
|
-
when
|
136
|
+
when COLUMN_REF_RE1: "#{$1}.#{$2} AS #{$3}"
|
137
|
+
when COLUMN_REF_RE2: "#{$1} AS #{$2}"
|
138
|
+
when COLUMN_REF_RE3: "#{$1}.#{$2}"
|
131
139
|
else
|
132
140
|
s
|
133
141
|
end
|
@@ -147,4 +155,37 @@ class Symbol
|
|
147
155
|
end
|
148
156
|
end
|
149
157
|
|
158
|
+
module Sequel
|
159
|
+
# Facilitates time calculations by providing methods to convert from larger
|
160
|
+
# time units to seconds, and to convert relative time intervals to absolute
|
161
|
+
# ones. This module duplicates some of the functionality provided by Rails'
|
162
|
+
# ActiveSupport::CoreExtensions::Numeric::Time module.
|
163
|
+
module NumericExtensions
|
164
|
+
MINUTE = 60
|
165
|
+
HOUR = 3600
|
166
|
+
DAY = 86400
|
167
|
+
WEEK = DAY * 7
|
168
|
+
|
169
|
+
# Converts self from minutes to seconds
|
170
|
+
def minutes; self * MINUTE; end; alias_method :minute, :minutes
|
171
|
+
# Converts self from hours to seconds
|
172
|
+
def hours; self * HOUR; end; alias_method :hour, :hours
|
173
|
+
# Converts self from days to seconds
|
174
|
+
def days; self * DAY; end; alias_method :day, :days
|
175
|
+
# Converts self from weeks to seconds
|
176
|
+
def weeks; self * WEEK; end; alias_method :week, :weeks
|
177
|
+
|
178
|
+
# Returns the time at now - self.
|
179
|
+
def ago(t = Time.now); t - self; end
|
180
|
+
alias_method :before, :ago
|
150
181
|
|
182
|
+
# Returns the time at now + self.
|
183
|
+
def from_now(t = Time.now); t + self; end
|
184
|
+
alias_method :since, :from_now
|
185
|
+
|
186
|
+
# Extends the Numeric class with numeric extensions.
|
187
|
+
def self.enable
|
188
|
+
Numeric.send(:include, self)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
data/lib/sequel/database.rb
CHANGED
@@ -180,7 +180,7 @@ module Sequel
|
|
180
180
|
|
181
181
|
# Drops one or more tables corresponding to the given table names.
|
182
182
|
def drop_table(*names)
|
183
|
-
|
183
|
+
names.each {|n| execute(drop_table_sql(n))}
|
184
184
|
end
|
185
185
|
|
186
186
|
# Returns true if the given table exists.
|
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -438,7 +438,7 @@ module Sequel
|
|
438
438
|
# 'INSERT INTO items (a, b) VALUES (1, 2)'
|
439
439
|
def insert_sql(*values)
|
440
440
|
if values.empty?
|
441
|
-
"INSERT INTO #{@opts[:from]} DEFAULT VALUES
|
441
|
+
"INSERT INTO #{@opts[:from]} DEFAULT VALUES"
|
442
442
|
else
|
443
443
|
values = values[0] if values.size == 1
|
444
444
|
case values
|
@@ -446,27 +446,27 @@ module Sequel
|
|
446
446
|
insert_sql(values.values)
|
447
447
|
when Array
|
448
448
|
if values.empty?
|
449
|
-
"INSERT INTO #{@opts[:from]} DEFAULT VALUES
|
450
|
-
elsif values.
|
451
|
-
fl = values.
|
449
|
+
"INSERT INTO #{@opts[:from]} DEFAULT VALUES"
|
450
|
+
elsif values.keys
|
451
|
+
fl = values.keys
|
452
452
|
vl = transform_save(values.values).map {|v| literal(v)}
|
453
|
-
"INSERT INTO #{@opts[:from]} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})
|
453
|
+
"INSERT INTO #{@opts[:from]} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
|
454
454
|
else
|
455
|
-
"INSERT INTO #{@opts[:from]} VALUES (#{literal(values)})
|
455
|
+
"INSERT INTO #{@opts[:from]} VALUES (#{literal(values)})"
|
456
456
|
end
|
457
457
|
when Hash
|
458
458
|
values = transform_save(values) if @transform
|
459
459
|
if values.empty?
|
460
|
-
"INSERT INTO #{@opts[:from]} DEFAULT VALUES
|
460
|
+
"INSERT INTO #{@opts[:from]} DEFAULT VALUES"
|
461
461
|
else
|
462
462
|
fl, vl = [], []
|
463
463
|
values.each {|k, v| fl << column_name(k); vl << literal(v)}
|
464
|
-
"INSERT INTO #{@opts[:from]} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})
|
464
|
+
"INSERT INTO #{@opts[:from]} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
|
465
465
|
end
|
466
466
|
when Dataset
|
467
|
-
"INSERT INTO #{@opts[:from]} #{literal(values)}
|
467
|
+
"INSERT INTO #{@opts[:from]} #{literal(values)}"
|
468
468
|
else
|
469
|
-
"INSERT INTO #{@opts[:from]} VALUES (#{literal(values)})
|
469
|
+
"INSERT INTO #{@opts[:from]} VALUES (#{literal(values)})"
|
470
470
|
end
|
471
471
|
end
|
472
472
|
end
|
@@ -484,7 +484,7 @@ module Sequel
|
|
484
484
|
raise SequelError, "Can't update a joined dataset"
|
485
485
|
end
|
486
486
|
|
487
|
-
if values.is_a?(Array) && values.
|
487
|
+
if values.is_a?(Array) && values.keys
|
488
488
|
values = values.to_hash
|
489
489
|
end
|
490
490
|
values = transform_save(values) if @transform
|
data/lib/sequel/mysql.rb
CHANGED
@@ -96,9 +96,9 @@ module Sequel
|
|
96
96
|
@opts[:database], @opts[:port])
|
97
97
|
conn.query_with_result = false
|
98
98
|
if encoding = @opts[:encoding] || @opts[:charset]
|
99
|
-
conn.query("set character_set_connection = '#{encoding}'
|
100
|
-
conn.query("set character_set_client = '#{encoding}'
|
101
|
-
conn.query("set character_set_results = '#{encoding}'
|
99
|
+
conn.query("set character_set_connection = '#{encoding}'")
|
100
|
+
conn.query("set character_set_client = '#{encoding}'")
|
101
|
+
conn.query("set character_set_results = '#{encoding}'")
|
102
102
|
end
|
103
103
|
conn.reconnect = true
|
104
104
|
conn
|
@@ -172,20 +172,20 @@ module Sequel
|
|
172
172
|
end
|
173
173
|
|
174
174
|
class Dataset < Sequel::Dataset
|
175
|
-
|
175
|
+
UNQUOTABLE_COLUMN_RE = /^(`(.+)`)|\*$/.freeze
|
176
176
|
def quote_column(f)
|
177
|
-
(f.nil? || f.empty? || f =~
|
177
|
+
(f.nil? || f.empty? || f =~ UNQUOTABLE_COLUMN_RE) ? f : "`#{f}`"
|
178
178
|
end
|
179
179
|
|
180
|
-
|
181
|
-
|
180
|
+
COLUMN_EXPR_RE = /^([^\(]+\()?([^\.]+\.)?([^\s\)]+)?(\))?(\sAS\s(.+))?$/i.freeze
|
181
|
+
COLUMN_ORDER_RE = /^(.*) (DESC|ASC)$/i.freeze
|
182
182
|
def quoted_column_name(name)
|
183
183
|
case name
|
184
|
-
when
|
184
|
+
when COLUMN_EXPR_RE:
|
185
185
|
$6 ? \
|
186
186
|
"#{$1}#{$2}#{quote_column($3)}#{$4} AS #{quote_column($6)}" : \
|
187
187
|
"#{$1}#{$2}#{quote_column($3)}#{$4}"
|
188
|
-
when
|
188
|
+
when COLUMN_ORDER_RE: "#{quote_column($1)} #{$2}"
|
189
189
|
else
|
190
190
|
quote_column(name)
|
191
191
|
end
|
data/lib/sequel/postgres.rb
CHANGED
@@ -284,7 +284,7 @@ module Sequel
|
|
284
284
|
end
|
285
285
|
|
286
286
|
def drop_table_sql(name)
|
287
|
-
"DROP TABLE #{name} CASCADE
|
287
|
+
"DROP TABLE #{name} CASCADE"
|
288
288
|
end
|
289
289
|
end
|
290
290
|
|
@@ -350,7 +350,7 @@ module Sequel
|
|
350
350
|
analysis.join("\r\n")
|
351
351
|
end
|
352
352
|
|
353
|
-
LOCK = 'LOCK TABLE %s IN %s MODE
|
353
|
+
LOCK = 'LOCK TABLE %s IN %s MODE'.freeze
|
354
354
|
|
355
355
|
ACCESS_SHARE = 'ACCESS SHARE'.freeze
|
356
356
|
ROW_SHARE = 'ROW SHARE'.freeze
|
@@ -63,9 +63,9 @@ module Sequel
|
|
63
63
|
columns = index[:columns].join(COMMA_SEPARATOR)
|
64
64
|
index_name = index[:name] || default_index_name(table_name, index[:columns])
|
65
65
|
if index[:unique]
|
66
|
-
"CREATE UNIQUE INDEX #{index_name} ON #{table_name} (#{columns})
|
66
|
+
"CREATE UNIQUE INDEX #{index_name} ON #{table_name} (#{columns})"
|
67
67
|
else
|
68
|
-
"CREATE INDEX #{index_name} ON #{table_name} (#{columns})
|
68
|
+
"CREATE INDEX #{index_name} ON #{table_name} (#{columns})"
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -74,7 +74,7 @@ module Sequel
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def create_table_sql_list(name, columns, indexes = nil)
|
77
|
-
sql = ["CREATE TABLE #{name} (#{column_list_sql(columns)})
|
77
|
+
sql = ["CREATE TABLE #{name} (#{column_list_sql(columns)})"]
|
78
78
|
if indexes && !indexes.empty?
|
79
79
|
sql.concat(index_list_sql_list(name, indexes))
|
80
80
|
end
|
@@ -82,7 +82,7 @@ module Sequel
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def drop_table_sql(name)
|
85
|
-
"DROP TABLE #{name}
|
85
|
+
"DROP TABLE #{name}"
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
data/lib/sequel/sqlite.rb
CHANGED
@@ -61,11 +61,11 @@ module Sequel
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def pragma_get(name)
|
64
|
-
single_value("PRAGMA #{name}
|
64
|
+
single_value("PRAGMA #{name}")
|
65
65
|
end
|
66
66
|
|
67
67
|
def pragma_set(name, value)
|
68
|
-
execute("PRAGMA #{name} = #{value}
|
68
|
+
execute("PRAGMA #{name} = #{value}")
|
69
69
|
end
|
70
70
|
|
71
71
|
AUTO_VACUUM = {'0' => :none, '1' => :full, '2' => :incremental}.freeze
|
@@ -149,7 +149,7 @@ module Sequel
|
|
149
149
|
def array_tuples_fetch_rows(sql, &block)
|
150
150
|
@db.execute_select(sql) do |result|
|
151
151
|
@columns = result.columns.map {|c| c.to_sym}
|
152
|
-
result.each
|
152
|
+
result.each {|r| r.keys = @columns; block[r]}
|
153
153
|
end
|
154
154
|
end
|
155
155
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
class Worker < Thread
|
5
|
+
class WorkerStopError < RuntimeError; end
|
6
|
+
|
7
|
+
attr_reader :queue
|
8
|
+
|
9
|
+
def initialize(db = nil)
|
10
|
+
@queue = Queue.new
|
11
|
+
t = self
|
12
|
+
if db
|
13
|
+
super {db.transaction {t.work}}
|
14
|
+
else
|
15
|
+
super {t.work}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def work
|
20
|
+
begin
|
21
|
+
loop {@cur = @queue.pop; @cur.call; @cur = nil}
|
22
|
+
rescue WorkerStopError # do nothing
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def busy?
|
27
|
+
@cur || !@queue.empty?
|
28
|
+
end
|
29
|
+
|
30
|
+
def async(proc = nil, &block)
|
31
|
+
@queue << (proc || block)
|
32
|
+
end
|
33
|
+
alias_method :add, :async
|
34
|
+
alias_method :<<, :async
|
35
|
+
|
36
|
+
def join
|
37
|
+
while busy?
|
38
|
+
sleep 0.1
|
39
|
+
end
|
40
|
+
self.raise WorkerStopError
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -107,7 +107,7 @@ context "A MySQL dataset" do
|
|
107
107
|
'SELECT max(items.`name`) AS `max_name` FROM items'
|
108
108
|
|
109
109
|
@d.insert_sql(:value => 333).should == \
|
110
|
-
'INSERT INTO items (`value`) VALUES (333)
|
110
|
+
'INSERT INTO items (`value`) VALUES (333)'
|
111
111
|
end
|
112
112
|
|
113
113
|
specify "should support ORDER clause in UPDATE statements" do
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../../lib/sequel/oracle')
|
2
|
+
|
3
|
+
ORACLE_DB = Sequel('oracle://hr:hr@loalhost/XE')
|
4
|
+
if ORACLE_DB.table_exists?(:test)
|
5
|
+
ORACLE_DB.drop_table :test
|
6
|
+
end
|
7
|
+
ORACLE_DB.create_table :test do
|
8
|
+
text :name
|
9
|
+
integer :value
|
10
|
+
|
11
|
+
index :value
|
12
|
+
end
|
13
|
+
|
14
|
+
context "A Oracle database" do
|
15
|
+
specify "should provide disconnect functionality" do
|
16
|
+
ORACLE_DB.execute("select user from dual")
|
17
|
+
ORACLE_DB.pool.size.should == 1
|
18
|
+
ORACLE_DB.disconnect
|
19
|
+
ORACLE_DB.pool.size.should == 0
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "A Oracle dataset" do
|
24
|
+
setup do
|
25
|
+
@d = ORACLE_DB[:test]
|
26
|
+
@d.delete # remove all records
|
27
|
+
end
|
28
|
+
|
29
|
+
specify "should return the correct record count" do
|
30
|
+
@d.count.should == 0
|
31
|
+
@d << {:name => 'abc', :value => 123}
|
32
|
+
@d << {:name => 'abc', :value => 456}
|
33
|
+
@d << {:name => 'def', :value => 789}
|
34
|
+
@d.count.should == 3
|
35
|
+
end
|
36
|
+
|
37
|
+
specify "should return the correct records" do
|
38
|
+
@d.to_a.should == []
|
39
|
+
@d << {:name => 'abc', :value => 123}
|
40
|
+
@d << {:name => 'abc', :value => 456}
|
41
|
+
@d << {:name => 'def', :value => 789}
|
42
|
+
|
43
|
+
@d.order(:value).to_a.should == [
|
44
|
+
{:name => 'abc', :value => 123},
|
45
|
+
{:name => 'abc', :value => 456},
|
46
|
+
{:name => 'def', :value => 789}
|
47
|
+
]
|
48
|
+
end
|
49
|
+
|
50
|
+
specify "should update records correctly" do
|
51
|
+
@d << {:name => 'abc', :value => 123}
|
52
|
+
@d << {:name => 'abc', :value => 456}
|
53
|
+
@d << {:name => 'def', :value => 789}
|
54
|
+
@d.filter(:name => 'abc').update(:value => 530)
|
55
|
+
|
56
|
+
# the third record should stay the same
|
57
|
+
# floating-point precision bullshit
|
58
|
+
@d[:name => 'def'][:value].should == 789
|
59
|
+
@d.filter(:value => 530).count.should == 2
|
60
|
+
end
|
61
|
+
|
62
|
+
specify "should delete records correctly" do
|
63
|
+
@d << {:name => 'abc', :value => 123}
|
64
|
+
@d << {:name => 'abc', :value => 456}
|
65
|
+
@d << {:name => 'def', :value => 789}
|
66
|
+
@d.filter(:name => 'abc').delete
|
67
|
+
|
68
|
+
@d.count.should == 1
|
69
|
+
@d.first[:name].should == 'def'
|
70
|
+
end
|
71
|
+
|
72
|
+
specify "should be able to literalize booleans" do
|
73
|
+
proc {@d.literal(true)}.should_not raise_error
|
74
|
+
proc {@d.literal(false)}.should_not raise_error
|
75
|
+
end
|
76
|
+
|
77
|
+
specify "should support transactions" do
|
78
|
+
ORACLE_DB.transaction do
|
79
|
+
@d << {:name => 'abc', :value => 1}
|
80
|
+
end
|
81
|
+
|
82
|
+
@d.count.should == 1
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "A Oracle dataset in array tuples mode" do
|
87
|
+
setup do
|
88
|
+
@d = ORACLE_DB[:test]
|
89
|
+
@d.delete # remove all records
|
90
|
+
Sequel.use_array_tuples
|
91
|
+
end
|
92
|
+
|
93
|
+
teardown do
|
94
|
+
Sequel.use_hash_tuples
|
95
|
+
end
|
96
|
+
|
97
|
+
specify "should return the correct records" do
|
98
|
+
@d.to_a.should == []
|
99
|
+
@d << {:name => 'abc', :value => 123}
|
100
|
+
@d << {:name => 'abc', :value => 456}
|
101
|
+
@d << {:name => 'def', :value => 789}
|
102
|
+
|
103
|
+
@d.order(:value).select(:name, :value).to_a.should == [
|
104
|
+
['abc', 123],
|
105
|
+
['abc', 456],
|
106
|
+
['def', 789]
|
107
|
+
]
|
108
|
+
end
|
109
|
+
|
110
|
+
specify "should work correctly with transforms" do
|
111
|
+
@d.transform(:value => [proc {|v| v.to_s}, proc {|v| v.to_i}])
|
112
|
+
|
113
|
+
@d.to_a.should == []
|
114
|
+
@d << {:name => 'abc', :value => 123}
|
115
|
+
@d << {:name => 'abc', :value => 456}
|
116
|
+
@d << {:name => 'def', :value => 789}
|
117
|
+
|
118
|
+
@d.order(:value).select(:name, :value).to_a.should == [
|
119
|
+
['abc', '123'],
|
120
|
+
['abc', '456'],
|
121
|
+
['def', '789']
|
122
|
+
]
|
123
|
+
|
124
|
+
a = @d.order(:value).first
|
125
|
+
a.values.should == ['abc', '123']
|
126
|
+
a.keys.should == [:name, :value]
|
127
|
+
a[:name].should == 'abc'
|
128
|
+
a[:value].should == '123'
|
129
|
+
end
|
130
|
+
end
|